feat(i18n): migrate billing, triage, pharmacy pages to vue-i18n (206+120+60 keys)

This commit is contained in:
2026-06-24 22:04:53 +08:00
parent d0f2e21af5
commit 1a0e6aabb4
21 changed files with 2047 additions and 735 deletions

View File

@@ -686,5 +686,416 @@
"hospitalizationError": "An error occurred during hospitalization, please try again later!",
"infectiousReportSaved": "Infectious disease report saved successfully",
"defaultDepartment": "Cardiology"
},
"triage": {
"title": "Smart Triage Queue Management",
"exit": "Exit",
"backendConfig": "Backend Config",
"candidatePoolTitle": "① Smart Candidate Pool (Checked-in, Not Queued)",
"seqNo": "No.",
"patient": "Patient",
"age": "Age",
"ticketType": "Ticket Type",
"room": "Room",
"doctor": "Doctor",
"matchedRule": "Matched Rule",
"addToQueue": "Add to Queue >>",
"addAllToQueue": "Add All to Queue",
"queueTitle": "② Smart Queue (All Depts)",
"selectDate": "Select Date",
"query": "Query",
"today": "Today",
"queueOrder": "Queue #",
"waiting": "Waiting",
"status": "Status",
"removeFromQueue": "<< Remove from Queue",
"roomFilterTitle": "③ Room Quick Filter",
"all": "All",
"showOnlyWaiting": "Show Waiting Only",
"showAllStatus": "Show All Status",
"callPanelTitle": "④ Call Control Panel",
"currentCall": "Current Call",
"selectCall": "Select Call",
"nextPatient": "Next Patient",
"skip": "Skip",
"complete": "Complete",
"requeue": "Requeue",
"ledLabel": "⑤ LED",
"pleaseGoTo": "please go to",
"voiceLabel": "Voice",
"voiceCallText": "Number {number}, {name}, please go to {room} ({type})",
"ruleConfigTitle": "Smart Triage Rule Engine Config - Cardiology",
"addRule": "Add Rule",
"saveAll": "Save All",
"testRule": "Test Rule",
"rule": "Rule",
"ruleName": "Rule Name",
"placeholderRuleName": "Enter rule name",
"department": "Department",
"cardiology": "Cardiology",
"ruleDesc": "Rule Description",
"placeholderRuleDesc": "Enter rule description",
"priority": "Priority",
"weekDayActive": "Effective Days",
"conditionExpr": "Condition Expression(JSON)",
"quickGenerator": "Quick Generator",
"syntaxCheck": "Syntax Check",
"ageCondition": "Age Condition",
"clear": "Clear",
"ticketTypeLabel": "Ticket Type",
"placeholderSelectTicketType": "Select ticket type",
"expert": "Expert",
"normal": "Normal",
"specialNeeds": "Special",
"emergency": "Emergency",
"placeholderSelectDept": "Select department",
"cardiacSurgery": "Cardiac Surgery",
"neurology": "Neurology",
"placeholderDoctor": "Enter doctor name (fuzzy match)",
"customCondition": "Custom Condition",
"placeholderFieldName": "Field name (e.g. gender)",
"placeholderFieldValue": "Field value (e.g. Male)",
"previewJson": "Preview JSON",
"apply": "Apply",
"weekMon": "Mon",
"weekTue": "Tue",
"weekWed": "Wed",
"weekThu": "Thu",
"weekFri": "Fri",
"weekSat": "Sat",
"weekSun": "Sun",
"statusWaiting": "Waiting",
"statusCalling": "Calling",
"statusInConsultation": "In Consultation",
"statusCompleted": "Completed",
"statusSkipped": "Skipped",
"statusRefunded": "Refunded",
"statusFollowUp": "Follow-up",
"newRule": "New Rule",
"msgDataLoaded": "Data loaded from outpatient registration",
"msgSelectPatientToAdd": "Please select patients to add to queue first",
"msgAddedToQueue": "Successfully added {count} patient(s) to queue (saved)",
"msgAlreadyInQueue": "Selected patients already in queue, removed from candidate pool",
"msgAddFailed": "Failed to add to queue, please retry",
"msgAddFailedUnsaved": "Failed to add to queue (unsaved)",
"msgNoCandidates": "No patients in candidate pool",
"msgAllAlreadyInQueue": "All candidate patients already in queue, removed from pool",
"msgAddAllFailed": "Failed to add all, please retry",
"msgAddAllFailedUnsaved": "Failed to add all (unsaved)",
"msgRefreshed": "Refreshed (queue restored from database)",
"msgSelectQueryDate": "Please select a query date",
"msgLoadedHistory": "Loaded queue data for {date}",
"msgSwitchedToToday": "Switched to today's queue",
"msgExitNotImpl": "Exit feature not yet implemented",
"msgSelectPatientInQueue": "Please select a patient from the right queue first",
"msgMissingIdSelectCall": "Queue item missing ID, cannot save. Please refresh the page",
"msgAlreadyCalling": "This patient is already in \"Calling\" status",
"msgCanOnlyCallWaiting": "Can only call \"Waiting\" patients, current status: \"{status}\"",
"msgSelectCalledWithCount": "Select-call saved, {count} patient(s) currently calling",
"msgSelectCalledSingle": "Select-call saved",
"msgSelectCallFailed": "Select-call failed (unsaved)",
"msgNextCalled": "Next patient called (saved)",
"msgNoWaitingPatient": "No \"Waiting\" patients in current scope",
"msgSkipped": "Skipped (saved)",
"msgNoCallingPatient": "No \"Calling\" patients",
"msgCompleted": "Completed (saved)",
"msgRequeued": "Requeued (saved)",
"msgNoWaitingPatientRequeue": "No waiting patients",
"msgFillRuleNameAndPriority": "Please fill in rule name and priority",
"msgSelectWeekDays": "Please select effective days",
"msgJsonSyntaxError": "Condition expression JSON syntax error",
"msgRuleSaved": "Current rule saved",
"msgAllRulesSaved": "All rules saved (frontend simulation)",
"msgSyntaxCheckPassed": "Syntax check passed",
"msgAtLeastOneCondition": "Please set at least one condition",
"msgConditionApplied": "Condition expression generated and applied",
"msgTestRulePlaceholder": "Test rule feature pending backend integration",
"msgSelectPatientToRemove": "Please select a patient to remove from queue first",
"msgMissingIdRemove": "Queue item missing ID, cannot save delete. Please refresh",
"msgRemovedFromQueue": "{name} removed from queue, patient reappeared in candidate pool (saved)",
"msgRemoveFailed": "Failed to remove from queue (unsaved)",
"msgMissingIdSort": "Queue item missing ID, cannot save sort. Please refresh",
"msgOrderAdjusted": "Queue order adjusted (saved)",
"msgOrderAdjustFailed": "Queue order adjustment failed (unsaved)"
},
"pharmacy": {
"patientInfo": "Patient Info",
"placeholderNameOrId": "Enter name/ID number",
"dispenseStatus": "Dispense Status",
"placeholderSelectDispenseStatus": "Select dispense status",
"visitDate": "Visit Date",
"startDate": "Start Date",
"endDate": "End Date",
"name": "Name",
"gender": "Gender",
"age": "Age",
"phone": "Phone",
"visitDateCol": "Visit Date",
"preparer": "Preparer",
"placeholderPreparer": "Preparer",
"drugCategory": "Drug Category",
"placeholderDrugCategory": "Drug Category",
"westernChinese": "Western/Chinese Patent",
"chinese": "Chinese Herbal",
"project": "Project",
"placeholderProject": "Project",
"all": "All",
"drug": "Drug",
"consumable": "Consumable",
"batchDispense": "Batch Dispense",
"scan": "Scan",
"prescriptionPrint": "Print Prescription",
"totalAmount": "Total Amount",
"prescriptionNo": "Prescription No.",
"diagnosis": "Diagnosis",
"prescriptionType": "Prescription Type",
"itemName": "Item Name",
"merchandiseName": "Merchandise Name",
"dispenseQty": "Dispense Qty",
"lotNumber": "Lot Number",
"dispenseStatusCol": "Dispense Status",
"days": "Days",
"spec": "Spec",
"traceNo": "Trace No.",
"placeholderTraceNo": "Enter trace number",
"amount": "Amount",
"dispensePharmacy": "Dispense Pharmacy",
"manufacturer": "Manufacturer",
"orderingDoctor": "Ordering Doctor",
"frequency": "Frequency",
"usage": "Usage",
"operation": "Action",
"dispense": "Dispense",
"void": "Void",
"selectVoidReason": "Select Void Reason",
"placeholderSelectVoidReason": "Select void reason",
"confirm": "OK",
"cancel": "Cancel",
"printWarningNoTable": "Table not initialized, please refresh and retry",
"printWarningNoSelect": "No items selected for printing, print failed",
"printWarningNoData": "Failed to get print data, please retry later",
"printFailed": "Prescription print failed",
"msgDispenseSuccess": "Dispensed successfully",
"msgDispenseFailed": "Dispense failed",
"msgNoMatchTraceNo": "No trace number matched in inventory, please scan individually in the dispense list",
"msgOperationFailed": "Operation failed",
"msgInsufficientStock": "Insufficient stock for this lot",
"msgQtyExceedsTotal": "Dispense quantity cannot exceed total quantity",
"msgQtyBelowTotal": "Dispense quantity cannot be less than total quantity",
"msgSelectDispenseItem": "No items selected for dispensing, please reselect",
"msgSelectVoidReason": "Please select a void reason",
"msgNoDataSelected": "No data selected",
"voiding": "Voiding...",
"yuan": "yuan",
"remaining": "remaining",
"expDate": "exp"
},
"billing": {
"patientList": "Patient List",
"searchPlaceholder": "Enter patient name/medical record no.",
"searchPlaceholderName": "Enter patient name",
"chargeStatus": "Charge Status",
"startTime": "Start Time",
"endTime": "End Time",
"search": "Search",
"medicalRecordNo": "Medical Record No.",
"name": "Name",
"basicInfo": "Basic Info",
"gender": "Gender",
"age": "Age",
"department": "Department",
"visitTime": "Visit Time",
"chargeItems": "Charge Items",
"confirmCharge": "Confirm Charge",
"electronicCertificate": "E-Certificate",
"idCard": "ID Card",
"medicalInsuranceCard": "Insurance Card",
"insuranceToSelf": "Insurance to Self-Pay",
"selfToInsurance": "Self-Pay to Insurance",
"studentInsuranceToSelf": "Student Insurance to Self-Pay",
"studentSelfToInsurance": "Student Self-Pay to Insurance",
"totalAmount": "Total Amount",
"docNo": "Doc No.",
"itemName": "Charge Item",
"quantity": "Qty",
"medicalType": "Medical Type",
"insuranceCode": "Insurance Code",
"feeNature": "Fee Nature",
"amount": "Amount",
"cashier": "Cashier",
"operation": "Action",
"print": "Print",
"yuan": "yuan",
"chargeDate": "Charge Date",
"receivableAmount": "Receivable",
"refundAmount": "Refundable",
"discountAmount": "Discount",
"payMethod": "Payment Method",
"selectPayMethod": "Select Payment",
"payAmount": "Pay Amount",
"refundMethod": "Refund Method",
"selectRefundMethod": "Select Refund",
"refundAmountLabel": "Refund Amount",
"addPayMethod": "Add Payment Method",
"addRefundMethod": "Add Refund Method",
"amountSatisfied": "Amount satisfied, cannot add more",
"refundAmountSatisfied": "Amount satisfied, cannot add more",
"discount": "Discount",
"wechatPay": "Scan to Pay",
"viewResult": "View Result",
"payType": "Payment Type",
"actualTotal": "Actual Total",
"refundTotal": "Refund Total",
"changeAmount": "Change",
"confirm": "Confirm",
"cancel": "Cancel",
"selectChargeItem": "Please select a charge item",
"preSettleFail": "Pre-settlement failed",
"enterCorrectAmount": "Please enter correct amount",
"chargeFail": "Charge failed",
"chargeFailRetry": "Charge failed, please retry",
"printFail": "Print failed",
"opSuccess": "Operation successful",
"outpatientChargeDetail": "Outpatient Charge Detail",
"outpatientChargeReceipt": "Outpatient Charge Receipt",
"refundReason": "Refund Reason",
"enterReason": "Enter reason",
"enterReasonPlaceholder": "Enter reason",
"refundConfirm": "Confirm Refund",
"refundDate": "Refund Date",
"refundDocNo": "Payment Doc No.",
"itemDocNo": "Item Doc No.",
"itemNameCol": "Item Name",
"chargeStatusCol": "Charge Status",
"paymentTotal": "Payment Total",
"refundItem": "Refund",
"encounterNo": "Encounter No.",
"refundDocs": "Refund Documents",
"enterCorrectRefundAmount": "Please enter correct amount",
"invoiceNo": "Invoice No.",
"invoiceStatus": "Invoice Status",
"issued": "Issued",
"notIssued": "Not Issued",
"settleTime": "Settlement Time",
"startDate": "Start Date",
"endDate": "End Date",
"query": "Query",
"reset": "Reset",
"total": "Total",
"success": "Success",
"batchIssue": "Batch Issue",
"payStatus": "Pay Status",
"feeType": "Fee Type",
"insuranceSettleId": "Insurance Settle ID",
"chargeSerialNo": "Charge Serial No.",
"settleAmount": "Settle Amount",
"payAmountCol": "Pay Amount",
"settleTimeCol": "Settle Time",
"payResult": "Pay Result",
"printCount": "Print Count",
"chargeDetail": "Charge Detail",
"issueInvoice": "Issue E-Invoice",
"writeoffInvoice": "Writeoff Invoice",
"viewInvoice": "View Invoice",
"payDetail": "Payment Type",
"change": "Change",
"payment": "Payment",
"writeoffReason": "Writeoff Reason",
"writeoffSuccess": "Writeoff successful",
"patientBasicInfo": "Patient Basic Info",
"surgeryNo": "Surgery No.",
"surgeryName": "Surgery Name",
"cardRenewal": "Card Renewal",
"patientQuery": "Patient Query(Q)",
"confirmBtn": "Confirm (O)",
"closeBtn": "Close (C)",
"patientNameLabel": "Patient Name:",
"idCardLabel": "ID Card No.:",
"phoneLabel": "Phone No.:",
"outpatientNo": "Outpatient No.",
"newOutpatientNo": "New Outpatient No.:",
"enterNewOutpatientNo": "Enter new outpatient no.",
"patientArchiveQuery": "Patient Archive Query",
"confirmSelect": "Confirm(Q)",
"closeSelect": "Close(C)",
"birthDate": "Birth Date",
"seqNo": "No.",
"patientName": "Patient Name",
"searchPlaceholderPatient": "Enter patient name",
"payBusNo": "Payment No.",
"txnAmount": "Amount(Yuan)",
"txnType": "Transaction Type",
"payTypeCol": "Pay Method",
"txnTime": "Transaction Time",
"origTxnType": "Original Type",
"thirdPartyDiscount": "3rd Party Discount",
"errorMsg": "Error Message",
"queryResult": "Query Result",
"queryResultMsg": "Result Description",
"payResultQuery": "Pay Result Query",
"nextDayRefund": "Next-Day Refund",
"refundResultQuery": "Refund Result Query",
"registerChargeRecord": "Schedule",
"schedule": "Schedule",
"detail": "Detail",
"normal": "Normal",
"disabled": "Disabled",
"nameCol": "Name",
"dateCol": "Date",
"statusCol": "Status",
"wechat": "WeChat",
"alipay": "Alipay",
"unionpay": "UnionPay",
"cash": "Cash",
"discountLabel": "Discount",
"selfPay": "Self-Pay",
"enterCashAmount": "Enter cash amount",
"payMethodPlaceholder": " payment QR code",
"reading": "Reading...",
"patientCardRenewalSuccess": "Card Renewal Success",
"patientRenewalSuccessMsg": "Patient card renewal completed successfully!",
"pleaseEnterQuery": "Please enter at least one query condition",
"autoSelectUnique": "Auto-selected the only patient",
"noPatientFound": "No patient found",
"queryFail": "Query failed",
"queryFailRetry": "Query failed, please retry later",
"selectPatient": "Please select a patient",
"selectPatientWarning": "Patient selected, please click confirm",
"patientRenewalSuccess": "Card renewal successful!",
"patientRenewalFail": "Card renewal failed",
"patientRenewalFailCardExists": "Card renewal failed, card number already exists",
"closeConfirm": "Are you sure to close this page?",
"cancelClose": "Close cancelled",
"newCardNoCannotSame": "New card number cannot be the same as the original",
"pleaseQueryPatient": "Please query patient info first",
"registerChargeRecordTitle": "Registration Charge Records",
"reprintRegistration": "Reprint Registration",
"reprintTitle": "Registration Slip Reprint",
"reprintSubtitle": "Reprinting will invalidate the original slip and generate a new one",
"doctorName": "Doctor Name",
"serialNo": "Serial No.",
"totalLabel": "Total",
"medicalRecordFee": "Medical Record Fee",
"printTime": "Print Time",
"visitTimeLabel": "Appointment/Registration Time",
"enterCardNoSearch": "Enter card number to search",
"regRecordSelect": "Registration Record Selection",
"enterCardNo": "Please enter card number",
"noRegRecord": "No registration records found, please check the card number",
"queryFailMsg": "Query failed: {msg}",
"queryError": "Query error: {error}",
"reprintSuccess": "Reprint successful",
"reprintFail": "Reprint failed",
"reprintFailMsg": "Reprint failed: {error}",
"selectRegRecordFirst": "Please search and select a registration record first",
"printSuccess": "Print successful",
"printFailMsg": "Print failed: {error}",
"selectRegRecord": "Please select a registration record",
"getRegIdFail": "Failed to get registration record ID, please retry",
"processFail": "Processing failed: {error}",
"statusReserved": "Reserved",
"statusCompleted": "Completed",
"statusCancelled": "Cancelled",
"statusInProgress": "In Progress"
}
}

View File

@@ -686,5 +686,416 @@
"hospitalizationError": "Đã xảy ra lỗi trong quá trình nhập viện, vui lòng thử lại sau!",
"infectiousReportSaved": "Lưu thẻ báo cáo bệnh truyền nhiễm thành công",
"defaultDepartment": "Khoa Tim Mạch"
},
"triage": {
"title": "Quản Lý Hàng Chờ Phân Loại Thông Minh",
"exit": "Thoát",
"backendConfig": "Cấu Hình Backend",
"candidatePoolTitle": "① Hồ Ứng Viên Thông Minh (Đã Check-in, Chưa Vào Hàng Chờ)",
"seqNo": "STT",
"patient": "Bệnh Nhân",
"age": "Tuổi",
"ticketType": "Loại Vé",
"room": "Phòng",
"doctor": "Bác Sĩ",
"matchedRule": "Quy Tắc Khớp",
"addToQueue": "Thêm Vào Hàng Chờ >>",
"addAllToQueue": "Thêm Tất Cả Vào Hàng Chờ",
"queueTitle": "② Hàng Chờ Thông Minh (Tất Cả Khoa)",
"selectDate": "Chọn Ngày",
"query": "Tìm Kiếm",
"today": "Hôm Nay",
"queueOrder": "STT Chờ",
"waiting": "Đang Chờ",
"status": "Trạng Thái",
"removeFromQueue": "<< Rời Khỏi Hàng Chờ",
"roomFilterTitle": "③ Lọc Nhanh Theo Phòng",
"all": "Tất Cả",
"showOnlyWaiting": "Chỉ Hiện Đang Chờ",
"showAllStatus": "Hiện Tất Cả Trạng Thái",
"callPanelTitle": "④ Bảng Điều Khiển Gọi Số",
"currentCall": "Đang Gọi",
"selectCall": "Gọi Chọn",
"nextPatient": "Bệnh Nhân Tiếp",
"skip": "Bỏ Qua",
"complete": "Hoàn Thành",
"requeue": "Xếp Lại",
"ledLabel": "⑤ LED",
"pleaseGoTo": "vui lòng đến",
"voiceLabel": "Giọng Nói",
"voiceCallText": "Số {number}, {name}, vui lòng đến {room} ({type})",
"ruleConfigTitle": "Cấu Hình Động Cơ Quy Tắc Phân Loại - Tim Mạch",
"addRule": "Thêm Quy Tắc",
"saveAll": "Lưu Tất Cả",
"testRule": "Thử Nghiệm Quy Tắc",
"rule": "Quy Tắc",
"ruleName": "Tên Quy Tắc",
"placeholderRuleName": "Nhập tên quy tắc",
"department": "Khoa",
"cardiology": "Tim Mạch",
"ruleDesc": "Mô Tả Quy Tắc",
"placeholderRuleDesc": "Nhập mô tả quy tắc",
"priority": "Ưu Tiên",
"weekDayActive": "Ngày Hiệu Lực",
"conditionExpr": "Biểu Thức Điều Kiện(JSON)",
"quickGenerator": "Tạo Nhanh",
"syntaxCheck": "Kiểm Tra Cú Pháp",
"ageCondition": "Điều Kiện Tuổi",
"clear": "Xóa",
"ticketTypeLabel": "Loại Vé",
"placeholderSelectTicketType": "Chọn loại vé",
"expert": "Chuyên Gia",
"normal": "Bình Thường",
"specialNeeds": "Đặc Biệt",
"emergency": "Cấp Cứu",
"placeholderSelectDept": "Chọn khoa",
"cardiacSurgery": "Phẫu Thuật Tim",
"neurology": "Thần Kinh",
"placeholderDoctor": "Nhập tên bác sĩ (tìm mờ)",
"customCondition": "Điều Kiện Tùy Chỉnh",
"placeholderFieldName": "Tên trường (vd: gender)",
"placeholderFieldValue": "Giá trị (vd: Nam)",
"previewJson": "Xem Trước JSON",
"apply": "Áp Dụng",
"weekMon": "T2",
"weekTue": "T3",
"weekWed": "T4",
"weekThu": "T5",
"weekFri": "T6",
"weekSat": "T7",
"weekSun": "CN",
"statusWaiting": "Đang Chờ",
"statusCalling": "Đang Gọi",
"statusInConsultation": "Đang Khám",
"statusCompleted": "Hoàn Thành",
"statusSkipped": "Bỏ Qua",
"statusRefunded": "Đã Hoàn Phí",
"statusFollowUp": "Tái Khám",
"newRule": "Quy Tắc Mới",
"msgDataLoaded": "Đã tải dữ liệu từ đăng ký khám bệnh",
"msgSelectPatientToAdd": "Vui lòng chọn bệnh nhân để thêm vào hàng chờ",
"msgAddedToQueue": "Đã thêm {count} bệnh nhân vào hàng chờ (đã lưu)",
"msgAlreadyInQueue": "Bệnh nhân đã có trong hàng chờ, đã xóa khỏi hồ ứng viên",
"msgAddFailed": "Thêm vào hàng chờ thất bại, vui lòng thử lại",
"msgAddFailedUnsaved": "Thêm vào hàng chờ thất bại (chưa lưu)",
"msgNoCandidates": "Không có bệnh nhân trong hồ ứng viên",
"msgAllAlreadyInQueue": "Tất cả bệnh nhân đã có trong hàng chờ",
"msgAddAllFailed": "Thêm tất cả thất bại, vui lòng thử lại",
"msgAddAllFailedUnsaved": "Thêm tất cả thất bại (chưa lưu)",
"msgRefreshed": "Đã làm mới (hàng chờ đã khôi phục từ CSDL)",
"msgSelectQueryDate": "Vui lòng chọn ngày truy vấn",
"msgLoadedHistory": "Đã tải dữ liệu hàng chờ ngày {date}",
"msgSwitchedToToday": "Đã chuyển sang hàng chờ hôm nay",
"msgExitNotImpl": "Chức năng thoát chưa được triển khai",
"msgSelectPatientInQueue": "Vui lòng chọn bệnh nhân từ hàng chờ bên phải",
"msgMissingIdSelectCall": "Mục hàng chờ thiếu ID, không thể lưu. Vui lòng tải lại trang",
"msgAlreadyCalling": "Bệnh nhân này đang ở trạng thái \"Đang Gọi\"",
"msgCanOnlyCallWaiting": "Chỉ có thể gọi bệnh nhân \"Đang Chờ\", trạng thái hiện tại: \"{status}\"",
"msgSelectCalledWithCount": "Đã gọi chọn (đã lưu), hiện có {count} bệnh nhân đang được gọi",
"msgSelectCalledSingle": "Đã gọi chọn (đã lưu)",
"msgSelectCallFailed": "Gọi chọn thất bại (chưa lưu)",
"msgNextCalled": "Đã gọi bệnh nhân tiếp theo (đã lưu)",
"msgNoWaitingPatient": "Không có bệnh nhân \"Đang Chờ\" trong phạm vi",
"msgSkipped": "Đã bỏ qua (đã lưu)",
"msgNoCallingPatient": "Không có bệnh nhân \"Đang Gọi\"",
"msgCompleted": "Đã hoàn thành (đã lưu)",
"msgRequeued": "Đã xếp lại (đã lưu)",
"msgNoWaitingPatientRequeue": "Không có bệnh nhân đang chờ",
"msgFillRuleNameAndPriority": "Vui lòng điền tên quy tắc và mức ưu tiên",
"msgSelectWeekDays": "Vui lòng chọn ngày hiệu lực",
"msgJsonSyntaxError": "Lỗi cú pháp JSON biểu thức điều kiện",
"msgRuleSaved": "Đã lưu quy tắc hiện tại",
"msgAllRulesSaved": "Đã lưu tất cả quy tắc (mô phỏng frontend)",
"msgSyntaxCheckPassed": "Kiểm tra cú pháp thành công",
"msgAtLeastOneCondition": "Vui lòng đặt ít nhất một điều kiện",
"msgConditionApplied": "Biểu thức điều kiện đã được tạo và áp dụng",
"msgTestRulePlaceholder": "Chức năng thử nghiệm quy tắc đang chờ tích hợp backend",
"msgSelectPatientToRemove": "Vui lòng chọn bệnh nhân để rời khỏi hàng chờ",
"msgMissingIdRemove": "Mục hàng chờ thiếu ID, không thể xóa. Vui lòng tải lại",
"msgRemovedFromQueue": "Đã xóa {name} khỏi hàng chờ, bệnh nhân đã xuất hiện lại trong hồ (đã lưu)",
"msgRemoveFailed": "Rời khỏi hàng chờ thất bại (chưa lưu)",
"msgMissingIdSort": "Mục hàng chờ thiếu ID, không thể lưu sắp xếp. Vui lòng tải lại",
"msgOrderAdjusted": "Đã điều chỉnh thứ tự hàng chờ (đã lưu)",
"msgOrderAdjustFailed": "Điều chỉnh thứ tự thất bại (chưa lưu)"
},
"pharmacy": {
"patientInfo": "Thông Tin Bệnh Nhân",
"placeholderNameOrId": "Nhập tên/số giấy tờ",
"dispenseStatus": "Trạng Thái Phát Thuốc",
"placeholderSelectDispenseStatus": "Chọn trạng thái phát thuốc",
"visitDate": "Ngày Khám",
"startDate": "Ngày Bắt Đầu",
"endDate": "Ngày Kết Thúc",
"name": "Họ Tên",
"gender": "Giới Tính",
"age": "Tuổi",
"phone": "Điện Thoại",
"visitDateCol": "Ngày Khám",
"preparer": "Dược Sĩ Pha Chế",
"placeholderPreparer": "Dược Sĩ Pha Chế",
"drugCategory": "Phân Loại Thuốc",
"placeholderDrugCategory": "Phân Loại Thuốc",
"westernChinese": "Tây Y/Thuốc Hoàn",
"chinese": "Thuốc Nam",
"project": "Dự Án",
"placeholderProject": "Dự Án",
"all": "Tất Cả",
"drug": "Thuốc",
"consumable": "Vật Tư",
"batchDispense": "Phát Hàng Loạt",
"scan": "Quét Mã",
"prescriptionPrint": "In Đơn Thuốc",
"totalAmount": "Tổng Tiền",
"prescriptionNo": "Số Đơn",
"diagnosis": "Chẩn Đoán",
"prescriptionType": "Loại Đơn",
"itemName": "Tên Mục",
"merchandiseName": "Tên Hàng Hóa",
"dispenseQty": "SL Phát",
"lotNumber": "Số Lô",
"dispenseStatusCol": "Trạng Thái",
"days": "Số Ngày",
"spec": "Quy Cách",
"traceNo": "Mã Truy Xuất",
"placeholderTraceNo": "Nhập mã truy xuất",
"amount": "Thành Tiền",
"dispensePharmacy": "Nhà Thuốc",
"manufacturer": "Nhà Sản Xuất",
"orderingDoctor": "Bác Sĩ Kê Đơn",
"frequency": "Tần Suất",
"usage": "Cách Dùng",
"operation": "Thao Tác",
"dispense": "Phát",
"void": "Hủy",
"selectVoidReason": "Chọn Lý Do Hủy",
"placeholderSelectVoidReason": "Chọn lý do hủy",
"confirm": "Xác Nhận",
"cancel": "Hủy Bỏ",
"printWarningNoTable": "Bảng chưa sẵn sàng, vui lòng tải lại",
"printWarningNoSelect": "Chưa chọn mục để in, in thất bại",
"printWarningNoData": "Lấy dữ liệu in thất bại, vui lòng thử lại",
"printFailed": "In đơn thuốc thất bại",
"msgDispenseSuccess": "Phát thuốc thành công",
"msgDispenseFailed": "Phát thuốc thất bại",
"msgNoMatchTraceNo": "Không khớp mã truy xuất trong kho, vui lòng quét riêng trong danh sách",
"msgOperationFailed": "Thao tác thất bại",
"msgInsufficientStock": "Tồn kho lô này không đủ",
"msgQtyExceedsTotal": "Số lượng phát không được vượt quá tổng",
"msgQtyBelowTotal": "Số lượng phát không được nhỏ hơn tổng",
"msgSelectDispenseItem": "Chưa chọn mục để phát, vui lòng chọn lại",
"msgSelectVoidReason": "Vui lòng chọn lý do hủy",
"msgNoDataSelected": "Chưa chọn dữ liệu",
"voiding": "Đang hủy...",
"yuan": "đ",
"remaining": "còn lại",
"expDate": "HSD"
},
"billing": {
"patientList": "Danh sách bệnh nhân",
"searchPlaceholder": "Nhập tên/số bệnh án",
"searchPlaceholderName": "Nhập tên bệnh nhân",
"chargeStatus": "Trạng thái thu phí",
"startTime": "Thời gian bắt đầu",
"endTime": "Thời gian kết thúc",
"search": "Tìm kiếm",
"medicalRecordNo": "Số bệnh án",
"name": "Họ tên",
"basicInfo": "Thông tin cơ bản",
"gender": "Giới tính",
"age": "Tuổi",
"department": "Khoa",
"visitTime": "Thời gian khám",
"chargeItems": "Dịch vụ thu phí",
"confirmCharge": "Xác nhận thu phí",
"electronicCertificate": "Chứng từ điện tử",
"idCard": "CCCD",
"medicalInsuranceCard": "Thẻ BHYT",
"insuranceToSelf": "BHYT sang tự trả",
"selfToInsurance": "Tự trả sang BHYT",
"studentInsuranceToSelf": "BHYT sinh viên sang tự trả",
"studentSelfToInsurance": "Tự trả sang BHYT sinh viên",
"totalAmount": "Tổng cộng",
"docNo": "Số chứng từ",
"itemName": "Dịch vụ",
"quantity": "Số lượng",
"medicalType": "Loại y tế",
"insuranceCode": "Mã BHYT",
"feeNature": "Tính chất phí",
"amount": "Số tiền",
"cashier": "Thu ngân",
"operation": "Thao tác",
"print": "In",
"yuan": "đ",
"chargeDate": "Ngày thu phí",
"receivableAmount": "Số tiền phải thu",
"refundAmount": "Số tiền hoàn",
"discountAmount": "Giảm giá",
"payMethod": "Phương thức thanh toán",
"selectPayMethod": "Chọn phương thức",
"payAmount": "Số tiền thanh toán",
"refundMethod": "Phương thức hoàn tiền",
"selectRefundMethod": "Chọn phương thức",
"refundAmountLabel": "Số tiền hoàn",
"addPayMethod": "Thêm phương thức",
"addRefundMethod": "Thêm phương thức",
"amountSatisfied": "Đã đủ số tiền, không thể thêm",
"refundAmountSatisfied": "Đã đủ số tiền, không thể thêm",
"discount": "Giảm giá",
"wechatPay": "Quét mã thanh toán",
"viewResult": "Xem kết quả",
"payType": "Loại thanh toán",
"actualTotal": "Tổng thực thu",
"refundTotal": "Tổng hoàn lại",
"changeAmount": "Tiền thừa",
"confirm": "Xác nhận",
"cancel": "Hủy",
"selectChargeItem": "Vui lòng chọn dịch vụ",
"preSettleFail": "Tính trước thất bại",
"enterCorrectAmount": "Vui lòng nhập đúng số tiền",
"chargeFail": "Thu phí thất bại",
"chargeFailRetry": "Thu phí thất bại, vui lòng thử lại",
"printFail": "In thất bại",
"opSuccess": "Thao tác thành công",
"outpatientChargeDetail": "Chi tiết thu phí ngoại trú",
"outpatientChargeReceipt": "Biên lai thu phí ngoại trú",
"refundReason": "Lý do hoàn tiền",
"enterReason": "Nhập lý do",
"enterReasonPlaceholder": "Nhập lý do",
"refundConfirm": "Xác nhận hoàn tiền",
"refundDate": "Ngày hoàn tiền",
"refundDocNo": "Số CT thanh toán",
"itemDocNo": "Số CT dịch vụ",
"itemNameCol": "Tên dịch vụ",
"chargeStatusCol": "Trạng thái thu phí",
"paymentTotal": "Tổng thanh toán",
"refundItem": "Hoàn tiền",
"encounterNo": "Số khám",
"refundDocs": "Chứng từ hoàn",
"enterCorrectRefundAmount": "Vui lòng nhập đúng số tiền",
"invoiceNo": "Số hóa đơn",
"invoiceStatus": "Trạng thái hóa đơn",
"issued": "Đã phát hành",
"notIssued": "Chưa phát hành",
"settleTime": "Thời gian thanh toán",
"startDate": "Ngày bắt đầu",
"endDate": "Ngày kết thúc",
"query": "Tìm kiếm",
"reset": "Đặt lại",
"total": "Tổng",
"success": "Thành công",
"batchIssue": "Phát hành hàng loạt",
"payStatus": "Trạng thái TT",
"feeType": "Loại phí",
"insuranceSettleId": "Mã QT BHYT",
"chargeSerialNo": "Số serial thu phí",
"settleAmount": "Số tiền thanh toán",
"payAmountCol": "Số tiền TT",
"settleTimeCol": "Thời gian TT",
"payResult": "Kết quả TT",
"printCount": "Số lần in",
"chargeDetail": "Chi tiết thu phí",
"issueInvoice": "Phát hành HĐ điện tử",
"writeoffInvoice": "Hủy hóa đơn",
"viewInvoice": "Xem hóa đơn",
"payDetail": "Loại thanh toán",
"change": "Tiền thừa",
"payment": "Thanh toán",
"writeoffReason": "Lý do hủy",
"writeoffSuccess": "Hủy thành công",
"patientBasicInfo": "Thông tin BN cơ bản",
"surgeryNo": "Số phẫu thuật",
"surgeryName": "Tên phẫu thuật",
"cardRenewal": "Đổi thẻ",
"patientQuery": "Tìm BN (Q)",
"confirmBtn": "Xác nhận (O)",
"closeBtn": "Đóng (C)",
"patientNameLabel": "Tên BN:",
"idCardLabel": "Số CCCD:",
"phoneLabel": "Số ĐT:",
"outpatientNo": "Số ngoại trú",
"newOutpatientNo": "Số ngoại trú mới:",
"enterNewOutpatientNo": "Nhập số ngoại trú mới",
"patientArchiveQuery": "Tìm kiếm hồ sơ BN",
"confirmSelect": "Xác nhận(Q)",
"closeSelect": "Đóng(C)",
"birthDate": "Ngày sinh",
"seqNo": "STT",
"patientName": "Tên bệnh nhân",
"searchPlaceholderPatient": "Nhập tên bệnh nhân",
"payBusNo": "Số thanh toán",
"txnAmount": "Số tiền(đ)",
"txnType": "Loại giao dịch",
"payTypeCol": "Phương thức TT",
"txnTime": "Thời gian GD",
"origTxnType": "Loại GD gốc",
"thirdPartyDiscount": "KM bên thứ 3",
"errorMsg": "Thông báo lỗi",
"queryResult": "KQ tìm kiếm",
"queryResultMsg": "Mô tả KQ",
"payResultQuery": "Truy vấn KQ TT",
"nextDayRefund": "Hoàn ngày sau",
"refundResultQuery": "Truy vấn KQ hoàn",
"registerChargeRecord": "Lịch trực",
"schedule": "Lịch trực",
"detail": "Chi tiết",
"normal": "Bình thường",
"disabled": "Tắt",
"nameCol": "Tên",
"dateCol": "Ngày",
"statusCol": "Trạng thái",
"wechat": "WeChat",
"alipay": "Alipay",
"unionpay": "UnionPay",
"cash": "Tiền mặt",
"discountLabel": "Giảm giá",
"selfPay": "Tự trả",
"enterCashAmount": "Nhập số tiền mặt",
"payMethodPlaceholder": " mã QR thanh toán",
"reading": "Đang đọc...",
"patientCardRenewalSuccess": "Đổi thẻ thành công",
"patientRenewalSuccessMsg": "Đổi thẻ bệnh nhân thành công!",
"pleaseEnterQuery": "Vui lòng nhập ít nhất một điều kiện",
"autoSelectUnique": "Đã tự động chọn BN duy nhất",
"noPatientFound": "Không tìm thấy bệnh nhân",
"queryFail": "Tìm kiếm thất bại",
"queryFailRetry": "Tìm kiếm thất bại, vui lòng thử lại",
"selectPatient": "Vui lòng chọn bệnh nhân",
"selectPatientWarning": "Đã chọn BN, vui lòng nhấn xác nhận",
"patientRenewalSuccess": "Đổi thẻ thành công!",
"patientRenewalFail": "Đổi thẻ thất bại",
"patientRenewalFailCardExists": "Đổi thẻ thất bại, số thẻ đã tồn tại",
"closeConfirm": "Bạn có chắc muốn đóng trang này?",
"cancelClose": "Đã hủy thao tác đóng",
"newCardNoCannotSame": "Số thẻ mới không được trùng số cũ",
"pleaseQueryPatient": "Vui lòng tìm thông tin BN trước",
"registerChargeRecordTitle": "Lịch sử thu phí đăng ký",
"reprintRegistration": "In lại phiếu đăng ký",
"reprintTitle": "In lại phiếu đăng ký khám",
"reprintSubtitle": "In lại sẽ hủy phiếu cũ và tạo phiếu mới",
"doctorName": "Tên bác sĩ",
"serialNo": "Số serial",
"totalLabel": "Tổng cộng",
"medicalRecordFee": "Phí bệnh án",
"printTime": "Thời gian in",
"visitTimeLabel": "Thời gian hẹn/đăng ký",
"enterCardNoSearch": "Nhập số thẻ để tìm kiếm",
"regRecordSelect": "Chọn bản ghi đăng ký",
"enterCardNo": "Vui lòng nhập số thẻ",
"noRegRecord": "Không tìm thấy bản ghi đăng ký, vui lòng kiểm tra số thẻ",
"queryFailMsg": "Tìm kiếm thất bại: {msg}",
"queryError": "Lỗi tìm kiếm: {error}",
"reprintSuccess": "In lại thành công",
"reprintFail": "In lại thất bại",
"reprintFailMsg": "In lại thất bại: {error}",
"selectRegRecordFirst": "Vui lòng tìm và chọn bản ghi đăng ký trước",
"printSuccess": "In thành công",
"printFailMsg": "In thất bại: {error}",
"selectRegRecord": "Vui lòng chọn một bản ghi đăng ký",
"getRegIdFail": "Lấy ID bản ghi thất bại, vui lòng thử lại",
"processFail": "Xử lý thất bại: {error}",
"statusReserved": "Đã đặt",
"statusCompleted": "Hoàn thành",
"statusCancelled": "Đã hủy",
"statusInProgress": "Đang xử lý"
}
}

View File

@@ -685,5 +685,416 @@
"hospitalizationError": "办理住院过程中发生错误,请稍后重试!",
"infectiousReportSaved": "传染病报告卡保存成功",
"defaultDepartment": "心内科"
},
"triage": {
"title": "智能分诊排队管理",
"exit": "退出",
"backendConfig": "后台配置",
"candidatePoolTitle": "① 智能候选池 (已签到未入队)",
"seqNo": "序号",
"patient": "患者",
"age": "年龄",
"ticketType": "号别",
"room": "诊室",
"doctor": "医生",
"matchedRule": "命中规则",
"addToQueue": "加入队列 >>",
"addAllToQueue": "一键加入队列",
"queueTitle": "② 智能队列 (全科)",
"selectDate": "选择日期",
"query": "查询",
"today": "今天",
"queueOrder": "队序",
"waiting": "等待",
"status": "状态",
"removeFromQueue": "<< 移出队列",
"roomFilterTitle": "③ 诊室快速过滤栏",
"all": "全部",
"showOnlyWaiting": "只显示等待",
"showAllStatus": "显示全部状态",
"callPanelTitle": "④ 叫号控制板",
"currentCall": "当前呼叫",
"selectCall": "选呼",
"nextPatient": "下一患者",
"skip": "跳过",
"complete": "完成",
"requeue": "过号重排",
"ledLabel": "⑤ LED",
"pleaseGoTo": "请到",
"voiceLabel": "语音",
"voiceCallText": "请{number}号{name}到{room}({type})",
"ruleConfigTitle": "智能分诊规则引擎配置 - 心内科",
"addRule": "新增规则",
"saveAll": "保存全部",
"testRule": "测试规则",
"rule": "规则",
"ruleName": "规则名称",
"placeholderRuleName": "请输入规则名称",
"department": "科室",
"cardiology": "心内科",
"ruleDesc": "规则描述",
"placeholderRuleDesc": "请输入规则描述",
"priority": "优先级",
"weekDayActive": "周几生效",
"conditionExpr": "条件表达式(JSON)",
"quickGenerator": "快速生成器",
"syntaxCheck": "语法检查",
"ageCondition": "年龄条件",
"clear": "清除",
"ticketTypeLabel": "号别/类型",
"placeholderSelectTicketType": "请选择号别",
"expert": "专家",
"normal": "普通",
"specialNeeds": "特需",
"emergency": "急诊",
"placeholderSelectDept": "请选择科室",
"cardiacSurgery": "心外科",
"neurology": "神经内科",
"placeholderDoctor": "请输入医生姓名(支持模糊匹配)",
"customCondition": "自定义条件",
"placeholderFieldName": "字段名gender",
"placeholderFieldValue": "字段值(如:男)",
"previewJson": "预览JSON",
"apply": "应用",
"weekMon": "一",
"weekTue": "二",
"weekWed": "三",
"weekThu": "四",
"weekFri": "五",
"weekSat": "六",
"weekSun": "日",
"statusWaiting": "等待",
"statusCalling": "叫号中",
"statusInConsultation": "就诊中",
"statusCompleted": "已完成",
"statusSkipped": "跳过",
"statusRefunded": "已退费",
"statusFollowUp": "已随访",
"newRule": "新规则",
"msgDataLoaded": "已从门诊挂号接口加载数据",
"msgSelectPatientToAdd": "请先选择要加入队列的患者",
"msgAddedToQueue": "成功将 {count} 位患者加入队列(已保存)",
"msgAlreadyInQueue": "所选患者已在队列中,已从候选池移除",
"msgAddFailed": "加入队列失败,请重试",
"msgAddFailedUnsaved": "加入队列失败(未保存)",
"msgNoCandidates": "候选池中没有患者",
"msgAllAlreadyInQueue": "所有候选池患者已在队列中,已从候选池移除",
"msgAddAllFailed": "一键加入失败,请重试",
"msgAddAllFailedUnsaved": "一键加入失败(未保存)",
"msgRefreshed": "已刷新(已从数据库恢复队列)",
"msgSelectQueryDate": "请选择查询日期",
"msgLoadedHistory": "已加载 {date} 的队列数据",
"msgSwitchedToToday": "已切换到今天队列",
"msgExitNotImpl": "退出功能待实现",
"msgSelectPatientInQueue": "请先在右侧队列中选择一个患者",
"msgMissingIdSelectCall": "该队列项缺少ID无法保存选呼请先刷新页面",
"msgAlreadyCalling": "该患者已经是\"叫号中\"状态",
"msgCanOnlyCallWaiting": "只能选呼\"等待\"状态的患者,当前患者状态为:\"{status}\"",
"msgSelectCalledWithCount": "已选呼(已保存),当前共有 {count} 位患者处于\"叫号中\"状态",
"msgSelectCalledSingle": "已选呼(已保存)",
"msgSelectCallFailed": "选呼失败(未保存)",
"msgNextCalled": "已呼叫下一位(已保存)",
"msgNoWaitingPatient": "当前范围内没有\"等待\"的患者",
"msgSkipped": "已跳过(已保存)",
"msgNoCallingPatient": "当前没有\"叫号中\"的患者",
"msgCompleted": "已完成(已保存)",
"msgRequeued": "已过号重排(已保存)",
"msgNoWaitingPatientRequeue": "当前没有等待中的患者",
"msgFillRuleNameAndPriority": "请填写规则名称和优先级",
"msgSelectWeekDays": "请选择生效周几",
"msgJsonSyntaxError": "条件表达式 JSON 语法错误",
"msgRuleSaved": "当前规则已保存",
"msgAllRulesSaved": "全部规则已保存(前端模拟)",
"msgSyntaxCheckPassed": "语法检查通过",
"msgAtLeastOneCondition": "请至少设置一个条件",
"msgConditionApplied": "条件表达式已生成并应用",
"msgTestRulePlaceholder": "测试规则功能待接入后端,当前为占位",
"msgSelectPatientToRemove": "请先选择要移出队列的患者",
"msgMissingIdRemove": "该队列项缺少ID无法保存删除请先刷新页面",
"msgRemovedFromQueue": "已将 {name} 移出队列,患者已重新出现在候选池中(已保存)",
"msgRemoveFailed": "移出队列失败(未保存)",
"msgMissingIdSort": "该队列项缺少ID无法保存排序请先刷新页面",
"msgOrderAdjusted": "队列顺序已调整(已保存)",
"msgOrderAdjustFailed": "队列顺序调整失败(未保存)"
},
"pharmacy": {
"patientInfo": "患者信息",
"placeholderNameOrId": "请输入姓名/证件号",
"dispenseStatus": "发药状态",
"placeholderSelectDispenseStatus": "请选择发药状态",
"visitDate": "就诊日期",
"startDate": "开始日期",
"endDate": "结束日期",
"name": "姓名",
"gender": "性别",
"age": "年龄",
"phone": "电话",
"visitDateCol": "就诊日期",
"preparer": "调配药师",
"placeholderPreparer": "调配药师",
"drugCategory": "药品分类",
"placeholderDrugCategory": "药品分类",
"westernChinese": "西药中成药",
"chinese": "中药",
"project": "项目",
"placeholderProject": "项目",
"all": "全部",
"drug": "药品",
"consumable": "耗材",
"batchDispense": "批量发药",
"scan": "扫码",
"prescriptionPrint": "处方打印",
"totalAmount": "总金额",
"prescriptionNo": "处方号",
"diagnosis": "诊断",
"prescriptionType": "处方类型",
"itemName": "项目名称",
"merchandiseName": "商品名称",
"dispenseQty": "发药数量",
"lotNumber": "批次号",
"dispenseStatusCol": "发药状态",
"days": "天数",
"spec": "规格",
"traceNo": "追溯码",
"placeholderTraceNo": "请输入追溯码",
"amount": "金额",
"dispensePharmacy": "发药药房",
"manufacturer": "生产厂家",
"orderingDoctor": "开单医生",
"frequency": "频次",
"usage": "用法",
"operation": "操作",
"dispense": "发药",
"void": "作废",
"selectVoidReason": "选择作废原因",
"placeholderSelectVoidReason": "请选择作废原因",
"confirm": "确定",
"cancel": "取消",
"printWarningNoTable": "表格组件未初始化,请刷新页面重试",
"printWarningNoSelect": "未选择要打印的项目,请重新选择,打印失败",
"printWarningNoData": "获取打印数据失败,请稍后重试",
"printFailed": "处方打印失败",
"msgDispenseSuccess": "发药成功",
"msgDispenseFailed": "发药失败",
"msgNoMatchTraceNo": "未在库存中匹配到追溯码,请在发药列表中单独扫描",
"msgOperationFailed": "操作失败",
"msgInsufficientStock": "当前批次库存不足",
"msgQtyExceedsTotal": "发药数量不能大于总数量",
"msgQtyBelowTotal": "发药数量不能小于总数量",
"msgSelectDispenseItem": "未选择要发药的项目,请重新选择,发药失败",
"msgSelectVoidReason": "请选择作废原因",
"msgNoDataSelected": "未选择数据",
"voiding": "作废中...",
"yuan": "元",
"remaining": "剩余",
"expDate": "有效期至"
},
"billing": {
"patientList": "患者列表",
"searchPlaceholder": "请输入患者名/病历号",
"searchPlaceholderName": "请输入患者名",
"chargeStatus": "收费状态",
"startTime": "开始时间",
"endTime": "结束时间",
"search": "搜索",
"medicalRecordNo": "病历号",
"name": "姓名",
"basicInfo": "基本信息",
"gender": "性别",
"age": "年龄",
"department": "科室",
"visitTime": "就诊时间",
"chargeItems": "收费项目",
"confirmCharge": "确认收费",
"electronicCertificate": "电子凭证",
"idCard": "身份证",
"medicalInsuranceCard": "医保卡",
"insuranceToSelf": "医保转自费",
"selfToInsurance": "自费转医保",
"studentInsuranceToSelf": "学生医保转学生自费",
"studentSelfToInsurance": "学生自费转学生医保",
"totalAmount": "合计金额",
"docNo": "单据号",
"itemName": "收费项目",
"quantity": "数量",
"medicalType": "医疗类型",
"insuranceCode": "医保编码",
"feeNature": "费用性质",
"amount": "金额",
"cashier": "收款人",
"operation": "操作",
"print": "打印",
"yuan": "元",
"chargeDate": "收费日期",
"receivableAmount": "应收金额",
"refundAmount": "应退金额",
"discountAmount": "折扣金额",
"payMethod": "支付方式",
"selectPayMethod": "选择支付方式",
"payAmount": "支付金额",
"refundMethod": "退费方式",
"selectRefundMethod": "选择退费方式",
"refundAmountLabel": "退费金额",
"addPayMethod": "添加支付方式",
"addRefundMethod": "添加退费方式",
"amountSatisfied": "金额已满足应收,不可继续添加",
"refundAmountSatisfied": "金额已满足应退,不可继续添加",
"discount": "折扣",
"wechatPay": "扫码支付",
"viewResult": "查看结果",
"payType": "支付类型",
"actualTotal": "实收合计",
"refundTotal": "实退合计",
"changeAmount": "应找零",
"confirm": "确 定",
"cancel": "取 消",
"selectChargeItem": "请选择一条收费项目",
"preSettleFail": "预结算失败",
"enterCorrectAmount": "请输入正确的结算金额",
"chargeFail": "收费失败",
"chargeFailRetry": "收费失败,请重试",
"printFail": "打印失败",
"opSuccess": "操作成功",
"outpatientChargeDetail": "门诊收费明细",
"outpatientChargeReceipt": "门诊收费结算单",
"refundReason": "退费原因",
"enterReason": "请输入原因",
"enterReasonPlaceholder": "请输入原因",
"refundConfirm": "确认退费",
"refundDate": "退费日期",
"refundDocNo": "支付单据号",
"itemDocNo": "项目单据号",
"itemNameCol": "项目名称",
"chargeStatusCol": "收费状态",
"paymentTotal": "付款总额",
"refundItem": "退费",
"encounterNo": "就诊号",
"refundDocs": "退费单据",
"enterCorrectRefundAmount": "请输入正确的金额",
"invoiceNo": "发票号",
"invoiceStatus": "发票状态",
"issued": "已开具",
"notIssued": "未开具",
"settleTime": "结算时间",
"startDate": "开始日期",
"endDate": "结束日期",
"query": "查询",
"reset": "重置",
"total": "总数",
"success": "成功",
"batchIssue": "批量开具",
"payStatus": "支付状态",
"feeType": "费用类型",
"insuranceSettleId": "医保结算Id",
"chargeSerialNo": "收费流水号",
"settleAmount": "结算金额",
"payAmountCol": "支付金额",
"settleTimeCol": "结算时间",
"payResult": "支付结果",
"printCount": "打印次数",
"chargeDetail": "收费详情",
"issueInvoice": "开具电子发票",
"writeoffInvoice": "冲销发票",
"viewInvoice": "调阅发票",
"payDetail": "支付类型",
"change": "找零",
"payment": "交款",
"writeoffReason": "冲销原因",
"writeoffSuccess": "红冲成功",
"patientBasicInfo": "患者基本信息",
"surgeryNo": "手术单号",
"surgeryName": "手术名称",
"cardRenewal": "换卡处理",
"patientQuery": "病人查询(Q)",
"confirmBtn": "确定 (O)",
"closeBtn": "关闭 (C)",
"patientNameLabel": "病人姓名:",
"idCardLabel": "身份证号码:",
"phoneLabel": "手机号码:",
"outpatientNo": "门诊号码",
"newOutpatientNo": "新门诊号码:",
"enterNewOutpatientNo": "请输入新门诊号码",
"patientArchiveQuery": "病人档案查询",
"confirmSelect": "确认(Q)",
"closeSelect": "关闭(C)",
"birthDate": "出生年月",
"seqNo": "序号",
"patientName": "患者姓名",
"searchPlaceholderPatient": "请输入患者姓名",
"payBusNo": "支付单号",
"txnAmount": "交易金额(元)",
"txnType": "交易类型",
"payTypeCol": "支付方式",
"txnTime": "交易时间",
"origTxnType": "原交易类型",
"thirdPartyDiscount": "第三方优惠说明",
"errorMsg": "错误信息",
"queryResult": "查询结果",
"queryResultMsg": "查询结果说明",
"payResultQuery": "支付结果查询",
"nextDayRefund": "隔天退费",
"refundResultQuery": "退费结果查询",
"registerChargeRecord": "排班管理",
"schedule": "排班管理",
"detail": "详情",
"normal": "正常",
"disabled": "停用",
"nameCol": "名称",
"dateCol": "日期",
"statusCol": "状态",
"wechat": "微信",
"alipay": "支付宝",
"unionpay": "银联",
"cash": "现金",
"discountLabel": "优惠",
"selfPay": "自费",
"enterCashAmount": "请输入现金金额",
"payMethodPlaceholder": "支付二维码",
"reading": "正在读取...",
"patientCardRenewalSuccess": "换卡成功",
"patientRenewalSuccessMsg": "患者换卡操作已成功完成!",
"pleaseEnterQuery": "请至少输入一个查询条件",
"autoSelectUnique": "已自动选中唯一患者",
"noPatientFound": "未查询到患者信息",
"queryFail": "查询失败",
"queryFailRetry": "查询失败,请稍后重试",
"selectPatient": "请选择患者",
"selectPatientWarning": "已选择患者,请点击确定",
"patientRenewalSuccess": "换卡成功!",
"patientRenewalFail": "换卡失败",
"patientRenewalFailCardExists": "换卡失败,卡号已存在",
"closeConfirm": "确定要关闭此页面吗?",
"cancelClose": "已取消关闭操作",
"newCardNoCannotSame": "新门诊号码不能与原号码相同",
"pleaseQueryPatient": "请先查询患者信息",
"registerChargeRecordTitle": "挂号收费记录",
"reprintRegistration": "补打挂号单",
"reprintTitle": "挂号单重打",
"reprintSubtitle": "补打挂号单将作废原有的挂号单据并生成新的挂号单据",
"doctorName": "医生姓名",
"serialNo": "流水号",
"totalLabel": "合计",
"medicalRecordFee": "病历费",
"printTime": "打印时间",
"visitTimeLabel": "预约/挂号时间",
"enterCardNoSearch": "请输入就诊卡号检索条",
"regRecordSelect": "挂号记录选择",
"enterCardNo": "请输入就诊卡号",
"noRegRecord": "未查询到相关挂号记录,请检查就诊卡号是否正确",
"queryFailMsg": "查询失败: {msg}",
"queryError": "查询出错: {error}",
"reprintSuccess": "补打挂号成功",
"reprintFail": "补打挂号失败",
"reprintFailMsg": "补打挂号失败: {error}",
"selectRegRecordFirst": "请先搜索并选择挂号记录",
"printSuccess": "打印成功",
"printFailMsg": "打印失败: {error}",
"selectRegRecord": "请选择一条挂号记录",
"getRegIdFail": "获取挂号记录ID失败请重试",
"processFail": "处理失败: {error}",
"statusReserved": "已预约",
"statusCompleted": "已完成",
"statusCancelled": "已取消",
"statusInProgress": "进行中"
}
}

View File

@@ -1,4 +1,4 @@
<template>
<template>
<div class="app-continer">
<div style="margin: 15px 0; padding: 0 20px">
<el-form
@@ -8,38 +8,38 @@
label-width="90px"
>
<el-form-item
label="患者姓名:"
:label="$t('billing.patientName') + ''"
prop="searchKey"
>
<el-input
v-model="queryParams.searchKey"
placeholder="患者姓名"
:placeholder="$t('billing.searchPlaceholderPatient')"
clearable
style="width: 240px"
@keyup.enter="getClinicRecord"
/>
</el-form-item>
<el-form-item
label="发票号:"
:label="$t('billing.invoiceNo') + ''"
prop="invoiceNo"
label-width="120px"
>
<el-input
v-model="queryParams.invoiceNo"
placeholder="发票号"
:placeholder="$t('billing.invoiceNo')"
clearable
style="width: 240px"
@keyup.enter="getClinicRecord"
/>
</el-form-item>
<el-form-item
label="发票状态:"
:label="$t('billing.invoiceStatus') + ''"
prop="invoiceStatus"
>
<el-select
v-model="queryParams.invoiceStatus"
select
placeholder="发票状态"
:placeholder="$t('billing.invoiceStatus')"
clearable
style="width: 240px"
@keyup.enter="getClinicRecord"
@@ -53,14 +53,14 @@
</el-select>
</el-form-item>
<el-form-item
label="结算时间:"
:label="$t('billing.settleTime') + ''"
prop="activeFlag"
>
<el-date-picker
v-model="occurrenceTime"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:start-placeholder="$t('billing.startDate')"
:end-placeholder="$t('billing.endDate')"
style="width: 300px; margin-bottom: 10px; margin-left: 20px"
value-format="YYYY-MM-DD"
:clearable="false"
@@ -73,21 +73,21 @@
plain
@click="getClinicRecord"
>
查询
{{ $t('billing.query') }}
</el-button>
<el-button
type="warning"
plain
@click="handleReset"
>
重置
{{ $t('billing.reset') }}
</el-button>
</div>
</el-form>
</div>
<div style="float: right; margin: 0 20px 10px 0">
<span style="margin-right: 20px">
{{ '总数:' + count + '/' + '成功' + successCount }}
{{ $t('billing.total') + '' + count + '/' + $t('billing.success') + '' + successCount }}
</span>
<el-button
type="primary"
@@ -95,7 +95,7 @@
plain
@click="handleBatchProcess"
>
批量开具
{{ $t('billing.batchIssue') }}
</el-button>
</div>
<vxe-table
@@ -104,44 +104,44 @@
>
<!-- <vxe-column title="计算类型" align="center" field="statusEnum_enumText" /> -->
<vxe-column
title="患者姓名"
:title="$t('billing.patientName')"
align="center"
field="patientName"
show-overflow="title"
/>
<vxe-column
title="支付状态"
:title="$t('billing.payStatus')"
align="center"
field="statusEnum_dictText"
show-overflow="title"
/>
<vxe-column
title="费用类型"
:title="$t('billing.feeType')"
align="center"
field="paymentEnum_dictText"
show-overflow="title"
/>
<vxe-column
title="医保结算Id"
:title="$t('billing.insuranceSettleId')"
align="center"
field="ybSettleIds"
show-overflow="title"
/>
<vxe-column
title="收费流水号"
:title="$t('billing.chargeSerialNo')"
align="center"
field="paymentNo"
width="280"
show-overflow="title"
/>
<vxe-column
title="发票号"
:title="$t('billing.invoiceNo')"
align="center"
field="invoiceNo"
show-overflow="title"
/>
<vxe-column
title="结算金额"
:title="$t('billing.settleAmount')"
align="right"
field="tenderedAmount"
header-align="center"
@@ -149,11 +149,11 @@
show-overflow="title"
>
<template #default="scope">
<span>{{ scope.row.tenderedAmount + ' ' }}</span>
<span>{{ scope.row.tenderedAmount + ' ' + $t('billing.yuan') }}</span>
</template>
</vxe-column>
<vxe-column
title="支付金额"
:title="$t('billing.payAmountCol')"
align="right"
field="displayAmount"
header-align="center"
@@ -161,12 +161,12 @@
show-overflow="title"
>
<template #default="scope">
<span>{{ scope.row.displayAmount + ' ' }}</span>
<span>{{ scope.row.displayAmount + ' ' + $t('billing.yuan') }}</span>
</template>
</vxe-column>
<vxe-column
key="billDate"
title="结算时间"
:title="$t('billing.settleTimeCol')"
align="center"
field="billDate"
@@ -177,26 +177,26 @@
</template>
</vxe-column>
<vxe-column
title="收款人"
:title="$t('billing.cashier')"
align="center"
field="entererName"
show-overflow="title"
/>
<!-- <vxe-column title="医生" align="center" field="paymentEnum_enumText" /> -->
<vxe-column
title="支付结果"
:title="$t('billing.payResult')"
align="center"
field="outcomeEnum_dictText"
show-overflow="title"
/>
<vxe-column
title="打印次数"
:title="$t('billing.printCount')"
align="center"
field="printCount"
show-overflow="title"
/>
<vxe-column
title="操作"
:title="$t('billing.operation')"
align="center"
field="paymentEnum_enumText"
width="340"
@@ -209,7 +209,7 @@
link
@click="handleOpen(scope.row,4)"
>
收费详情
{{ $t('billing.chargeDetail') }}
</el-button>
<el-button
type="primary"
@@ -217,7 +217,7 @@
:disabled="scope.row.invoiceNo || scope.row.statusEnum == 3"
@click="handleOpen(scope.row,1)"
>
开具电子发票
{{ $t('billing.issueInvoice') }}
</el-button>
<el-button
:disabled="!scope.row.relationId"
@@ -225,7 +225,7 @@
link
@click="handleOpenReasonDialog(scope.row)"
>
冲销发票
{{ $t('billing.writeoffInvoice') }}
</el-button>
<el-button
type="primary"
@@ -233,7 +233,7 @@
:disabled="!scope.row.invoiceNo"
@click="handleOpen(scope.row,3)"
>
调阅发票
{{ $t('billing.viewInvoice') }}
</el-button>
</template>
</vxe-column>
@@ -247,7 +247,7 @@
/>
<el-dialog
v-model="paymentDetailShow"
title="收费详情"
:title="$t('billing.chargeDetail')"
width="1000"
teleported
style="height:90vh"
@@ -258,25 +258,25 @@
style="height: 80vh"
>
<vxe-column
title="支付类型"
:title="$t('billing.payType')"
align="center"
field="payEnum_dictText"
show-overflow="title"
/>
<vxe-column
title="金额"
:title="$t('billing.amount')"
align="center"
field="amount"
show-overflow="title"
/>
<vxe-column
title="找零"
:title="$t('billing.change')"
align="center"
field="returnAmount"
show-overflow="title"
/>
<vxe-column
title="交款"
:title="$t('billing.payment')"
align="center"
field="chargeAmount"
show-overflow="title"
@@ -285,17 +285,17 @@
</el-dialog>
<el-dialog
v-model="reasonDialogVisible"
title="请输入原因"
:title="$t('billing.enterReason')"
width="30%"
>
<el-form
:model="reasonForm"
label-width="80px"
>
<el-form-item label="冲销原因">
<el-form-item :label="$t('billing.writeoffReason')">
<el-input
v-model="reasonForm.reason"
placeholder="请输入原因"
:placeholder="$t('billing.enterReasonPlaceholder')"
type="textarea"
:rows="3"
/>
@@ -303,11 +303,11 @@
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="reasonDialogVisible = false"> </el-button>
<el-button @click="reasonDialogVisible = false">{{ $t('billing.cancel') }}</el-button>
<el-button
type="primary"
@click="submitReason"
> </el-button>
>{{ $t('billing.confirm') }}</el-button>
</span>
</template>
</el-dialog>
@@ -315,6 +315,8 @@
</template>
<script setup name="ClinicRecord">
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
import {getList, invoiceOpen, invoiceReissue, invoiceWriteoff, paymentDetail} from './components/api.js';
import {formatDate} from '@/utils/index';
@@ -330,9 +332,9 @@ const queryParams = ref({
invoiceStatus:1,
kinsEnum: 1
});
const invoiceStatusList = ref([
{ value: 1, label: '已开具' },
{ value: 0, label: '未开具' },
const invoiceStatusList = computed(() => [
{ value: 1, label: t('billing.issued') },
{ value: 0, label: t('billing.notIssued') },
]);
const paymentDetailShow = ref(false)
const clinicRecord = ref([]);
@@ -372,7 +374,7 @@ function handleOpenReasonDialog(row) {
// 提交原因
function submitReason() {
if (!reasonForm.value.reason.trim()) {
proxy.$message.warning('请输入原因');
proxy.$message.warning(t('billing.enterReason'));
return;
}
@@ -381,7 +383,7 @@ function submitReason() {
if(res.data.includes(" 电子票据红冲失败")){
proxy.$message.error(res.data);
}else{
proxy.$message.success('红冲成功');
proxy.$message.success(t('billing.writeoffSuccess'));
// 关闭弹窗
reasonDialogVisible.value = false;

View File

@@ -1,7 +1,7 @@
<template>
<template>
<el-dialog
v-model="props.open"
title="确认收费"
:title="$t('billing.confirmCharge')"
width="700px"
teleported
destroy-on-close
@@ -13,33 +13,33 @@
size="large"
style="display: block; margin-bottom: 15px"
>
收费日期{{ currentDate }}
{{ $t('billing.chargeDate') }}{{ currentDate }}
</el-text>
<el-text size="large">
费用性质{{ '自费' }}
{{ $t('billing.feeNature') }}{{ $t('billing.selfPay') }}
</el-text>
<div class="amount-row">
<el-text size="large">
应收金额
{{ $t('billing.receivableAmount') }}
</el-text>
<el-text
size="large"
type="primary"
class="amount"
>
{{ props.totalAmount.toFixed(2) + ' ' }}
{{ props.totalAmount.toFixed(2) + ' ' + $t('billing.yuan') }}
</el-text>
</div>
<div class="amount-row">
<el-text size="large">
折扣金额
{{ $t('billing.discountAmount') }}
</el-text>
<el-text
size="large"
type="warning"
class="amount"
>
{{ discountAmount.toFixed(2) + ' ' }}
{{ discountAmount.toFixed(2) + ' ' + $t('billing.yuan') }}
</el-text>
</div>
@@ -53,7 +53,7 @@
v-show="item.payEnum != 220500"
class="payment-item"
>
<span>支付方式</span>
<span>{{ $t('billing.payMethod') }}</span>
<img
v-if="item.payEnum == 220100 || item.payEnum == 220200"
:src="imgs[item.payEnum == 220100 ? 0 : 1]"
@@ -61,7 +61,7 @@
>
<el-select
v-model="item.payEnum"
placeholder="选择支付方式"
:placeholder="$t('billing.selectPayMethod')"
style="width: 160px"
@change="(value) => clearAmount(index, value)"
>
@@ -73,7 +73,7 @@
:disabled="isMethodDisabled(payEnum)"
/>
</el-select>
<span>支付金额</span>
<span>{{ $t('billing.payAmount') }}</span>
<div class="suffix-wrapper">
<el-input-number
v-model="item.amount"
@@ -81,11 +81,11 @@
:min="0"
:max="getMax(index)"
:controls="false"
placeholder="金额"
:placeholder="$t('billing.amount')"
class="amount-input"
@change="handleAmountChange"
/>
<span class="suffix-text"></span>
<span class="suffix-text">{{ $t('billing.yuan') }}</span>
</div>
<el-button
v-if="index > 0"
@@ -103,21 +103,21 @@
:disabled="formData.selfPay.length >= 4 || remainingAmount <= 0"
@click="addPayment"
>
添加支付方式
{{ $t('billing.addPayMethod') }}
</el-button>
<el-text
v-if="remainingAmount <= 0"
type="danger"
class="tip"
>
金额已满足应收不可继续添加
{{ $t('billing.amountSatisfied') }}
</el-text>
</div>
<div
v-if="userStore.hospitalName == '同一医院'"
style="margin-top: 10px"
>
<span>折扣</span>
<span>{{ $t('billing.discount') }}</span>
<el-radio-group
v-model="discountRadio"
@change="handleDiscountChange"
@@ -132,7 +132,7 @@
</div>
</div>
<div class="payment-item">
<span>{{ payTypeText }}支付</span>
<span>{{ payTypeTextDisplay }}{{ $t('billing.payMethod') }}</span>
<el-input
ref="txtCodeRef"
v-model="txtCode"
@@ -144,14 +144,14 @@
type="primary"
@click="handleWxPay()"
>
扫码支付
{{ $t('billing.wechatPay') }}
</el-button>
<el-button
link
type="primary"
@click="getWxPayResult()"
>
查看结果
{{ $t('billing.viewResult') }}
</el-button>
</div>
<div>
@@ -162,18 +162,18 @@
>
<vxe-column
field="payEnumText"
title="支付类型"
:title="$t('billing.payType')"
align="center"
/>
<vxe-column
field="amount"
title="金额"
:title="$t('billing.amount')"
header-align="center"
align="right"
width="200"
>
<template #default="scope">
{{ scope.row.amount ? scope.row.amount + ' ' : '-' }}
{{ scope.row.amount ? scope.row.amount + ' ' + $t('billing.yuan') : '-' }}
</template>
</vxe-column>
</vxe-table>
@@ -183,18 +183,18 @@
<el-space :size="30">
<div class="summary-item">
<el-text type="info">
实收合计
{{ $t('billing.actualTotal') }}
</el-text>
<el-text type="success">
{{ displayAmount + ' ' }}
{{ displayAmount + ' ' + $t('billing.yuan') }}
</el-text>
</div>
<div class="summary-item">
<el-text type="info">
应找零
{{ $t('billing.changeAmount') }}
</el-text>
<el-text type="warning">
{{ returnedAmount + ' ' }}
{{ returnedAmount + ' ' + $t('billing.yuan') }}
</el-text>
</div>
</el-space>
@@ -207,14 +207,14 @@
:disabled="dialogLoading"
@click="throttledGetList"
>
{{ $t('billing.confirm') }}
</el-button>
<!-- <el-button type="primary" @click="print()" :disabled="dialogLoading"> </el-button> -->
<el-button
:disabled="dialogLoading"
@click="close"
>
{{ $t('billing.cancel') }}
</el-button>
</div>
</template>
@@ -232,6 +232,9 @@ import templateJson from './template.json';
import printUtils, {PRINT_TEMPLATE} from '@/utils/printUtils';
import image1 from '../../../../assets/images/weixinzhifu.png';
import image2 from '../../../../assets/images/zhifubaozhifu.png';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const imgs = ref([image1, image2]);
const props = defineProps({
@@ -617,7 +620,7 @@ async function printReceipt(param) {
personType: param.contractName,
fixmedinsName: (param.fixmedinsName || '') + '门诊收费明细',
fixmedinsName: (param.fixmedinsName || '') + t('billing.outpatientChargeDetail'),
//电子收据二维码
pictureUrl: param.pictureUrl || 'https://chinaebill.com/img/xiaochengxu.png',
@@ -666,7 +669,7 @@ async function printReceipt(param) {
console.error('[ERROR] 错误详情:', error.message);
console.error('[ERROR] 错误堆栈:', error.stack);
console.log('========== 打印收费小票 - 异常结束 ==========');
proxy.$modal.msgError('打印失败: ' + error.message);
proxy.$modal.msgError(t('billing.printFail') + ': ' + error.message);
}
}
const throttledGetList = debounce(submit, 300);
@@ -709,7 +712,7 @@ async function submit() {
}, 0)
.toFixed(2);
if (parseFloat(amount) < parseFloat(formData.totalAmount.toFixed(2))) {
proxy.$modal.msgError('请输入正确的结算金额');
proxy.$modal.msgError(t('billing.enterCorrectAmount'));
return;
}
dialogLoading.value = true;
@@ -743,12 +746,12 @@ async function submit() {
});
}
} else {
proxy.$modal.msgError(res.msg || '收费失败');
proxy.$modal.msgError(res.msg || t('billing.chargeFail'));
}
})
.catch((error) => {
console.error('收费失败:', error);
proxy.$modal.msgError(error.message || '收费失败,请重试');
proxy.$modal.msgError(error.message || t('billing.chargeFailRetry'));
})
.finally(() => {
dialogLoading.value = false;
@@ -775,9 +778,9 @@ async function print() {
encounterBusNo: props.patientInfo.encounterBusNo, // 病例号
currentDate: currentDate.value, // 收费日期
chargedItems: props.chargedItems, // 收费项目
totalAmount: props.totalAmount.toFixed(2) + ' ', // 应收金额
displayAmount: displayAmount.value + ' ', // 实收金额
returnedAmount: returnedAmount.value + ' ', // 应找零
totalAmount: props.totalAmount.toFixed(2) + ' ' + t('billing.yuan'), // 应收金额
displayAmount: displayAmount.value + ' ' + t('billing.yuan'), // 实收金额
returnedAmount: returnedAmount.value + ' ' + t('billing.yuan'), // 应找零
},
],
};
@@ -790,19 +793,19 @@ async function print() {
const printerList = hiprintTemplate.getPrinterList();
console.log(hiprintTemplate, '打印机列表');
hiprintTemplate.print2(result.data[0], {
title: '门诊收费结算单',
title: t('billing.outpatientChargeReceipt'),
});
}
const currentDate = ref(new Date().toLocaleString());
const selfPayMethods = [
{ label: '现金', value: 220400, isWebPay: false },
{ label: '微信', value: 220100, isWebPay: true },
{ label: '支付宝', value: 220200, isWebPay: true },
{ label: '银联', value: 220300, isWebPay: true },
{ label: '优惠', value: 220500, isWebPay: false },
];
const selfPayMethods = computed(() => [
{ label: t('billing.cash'), labelKey: 'billing.cash', value: 220400, isWebPay: false },
{ label: t('billing.wechat'), labelKey: 'billing.wechat', value: 220100, isWebPay: true },
{ label: t('billing.alipay'), labelKey: 'billing.alipay', value: 220200, isWebPay: true },
{ label: t('billing.unionpay'), labelKey: 'billing.unionpay', value: 220300, isWebPay: true },
{ label: t('billing.discountLabel'), labelKey: 'billing.discountLabel', value: 220500, isWebPay: false },
]);
// 计算剩余可输入金额
const remainingAmount = computed(() => {
@@ -843,7 +846,7 @@ const isMethodDisabled = (option) => {
}
// 若已经选择了任一线上支付方式,则其他线上方式不可再选,仅允许现金等线下方式
const hasSelectedWebPay = selectedEnums.some((val) => {
const found = selfPayMethods.find((m) => m.value === val);
const found = selfPayMethods.value.find((m) => m.value === val);
return found ? found.isWebPay === true : false;
});
if (hasSelectedWebPay && option.isWebPay) {
@@ -870,17 +873,18 @@ const removePayment = (index) => {
formData.selfPay.splice(index, 1);
};
const payTypeText = ref('微信');
const payTypeText = ref('billing.wechat');
const payTypeTextDisplay = computed(() => t(payTypeText.value));
const payTypePlaceholder = computed(() => {
if (payTypeText.value === '现金') {
return '请输入现金金额';
if (payTypeText.value === 'billing.cash') {
return t('billing.enterCashAmount');
}
return payTypeText.value + '支付二维码';
return t(payTypeText.value) + t('billing.payMethodPlaceholder');
});
const clearAmount = (index, value) => {
const selectedOption = selfPayMethods.find((item) => item.value === value);
const selectedOption = selfPayMethods.value.find((item) => item.value === value);
if (selectedOption) {
payTypeText.value = selectedOption.label;
payTypeText.value = selectedOption.labelKey;
}
};

View File

@@ -7,12 +7,12 @@
>
<el-card style="width: 30%">
<template #header>
<span style="vertical-align: middle">患者列表</span>
<span style="vertical-align: middle">{{ $t('billing.patientList') }}</span>
</template>
<div style="width: 100%">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名/病历号"
:placeholder="$t('billing.searchPlaceholder')"
clearable
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
@keyup.enter="getPatientList"
@@ -27,7 +27,7 @@
<el-select
v-model="queryParams.statusEnum"
style="width: 48%; margin-bottom: 10px; margin-right: 10px"
placeholder="收费状态"
:placeholder="$t('billing.chargeStatus')"
@change="getPatientList"
>
<el-option
@@ -42,8 +42,8 @@
v-model="receptionTime"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
:start-placeholder="$t('billing.startTime')"
:end-placeholder="$t('billing.endTime')"
placement="bottom"
value-format="YYYY-MM-DD"
style="width: 84%; margin-bottom: 10px; margin-right: 10px"
@@ -54,7 +54,7 @@
style="margin-bottom: 10px"
@click="getPatientList"
>
搜索
{{ $t('billing.search') }}
</el-button>
</div>
<vxe-table
@@ -65,12 +65,12 @@
@cell-click="clickRow"
>
<vxe-column
title="病历号"
:title="$t('billing.medicalRecordNo')"
align="center"
field="encounterBusNo"
/>
<vxe-column
title="姓名"
:title="$t('billing.name')"
align="center"
field="patientName"
/>
@@ -80,7 +80,7 @@
</template>
</vxe-column> -->
<vxe-column
title="收费状态"
:title="$t('billing.chargeStatus')"
align="center"
field="statusEnum_enumText"
/>
@@ -90,22 +90,22 @@
<div style="width: 69%">
<el-card style="margin-bottom: 20px">
<template #header>
<span style="vertical-align: middle">基本信息</span>
<span style="vertical-align: middle">{{ $t('billing.basicInfo') }}</span>
</template>
<el-descriptions :column="5">
<el-descriptions-item label="姓名:">
<el-descriptions-item :label="$t('billing.name') + ':'">
{{ patientInfo.patientName }}
</el-descriptions-item>
<el-descriptions-item label="性别:">
<el-descriptions-item :label="$t('billing.gender') + ':'">
{{ patientInfo.genderEnum_enumText }}
</el-descriptions-item>
<el-descriptions-item label="年龄:">
<el-descriptions-item :label="$t('billing.age') + ':'">
{{ patientInfo.age }}
</el-descriptions-item>
<el-descriptions-item label="科室:">
<el-descriptions-item :label="$t('billing.department') + ':'">
{{ patientInfo.organizationName }}
</el-descriptions-item>
<el-descriptions-item label="就诊时间:">
<el-descriptions-item :label="$t('billing.visitTime') + ':'">
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-descriptions-item>
<!-- <el-descriptions-item label="身份证号:">{{ patientInfo.idCard }}</el-descriptions-item> -->
@@ -115,7 +115,7 @@
</el-card>
<el-card style="min-width: 1100px">
<template #header>
<span style="vertical-align: middle">收费项目</span>
<span style="vertical-align: middle">{{ $t('billing.chargeItems') }}</span>
</template>
<div style="margin-bottom: 10px">
<el-button
@@ -123,7 +123,7 @@
:disabled="buttonDisabled"
@click="confirmCharge()"
>
确认收费
{{ $t('billing.confirmCharge') }}
</el-button>
<el-button
type="primary"
@@ -131,7 +131,7 @@
style="width: 65px"
@click="handleReadCard('01')"
>
电子凭证
{{ $t('billing.electronicCertificate') }}
</el-button>
<el-button
type="primary"
@@ -140,7 +140,7 @@
:disabled="true"
@click="handleReadCard('02')"
>
身份证
{{ $t('billing.idCard') }}
</el-button>
<el-button
type="primary"
@@ -148,7 +148,7 @@
style="width: 65px"
@click="handleReadCard('03')"
>
医保卡
{{ $t('billing.medicalInsuranceCard') }}
</el-button>
<el-button
type="primary"
@@ -156,7 +156,7 @@
:disabled="buttonDisabled"
@click="payToSelt()"
>
医保转自费
{{ $t('billing.insuranceToSelf') }}
</el-button>
<el-button
type="primary"
@@ -164,7 +164,7 @@
:disabled="buttonDisabled"
@click="patToMedicalInsurance()"
>
自费转医保
{{ $t('billing.selfToInsurance') }}
</el-button>
<el-button
type="primary"
@@ -172,7 +172,7 @@
:disabled="buttonDisabled"
@click="studentPayTosStudentSelf()"
>
学生医保转学生自费
{{ $t('billing.studentInsuranceToSelf') }}
</el-button>
<el-button
type="primary"
@@ -180,11 +180,11 @@
:disabled="buttonDisabled"
@click="studentSelfToStudentPay()"
>
学生自费转学生医保
{{ $t('billing.studentSelfToInsurance') }}
</el-button>
</div>
<div style="text-align: right; padding-right: 20px; margin-bottom: 10px;">
<span style="font-weight: bold; font-size: 14px;">合计金额{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}</span>
<span style="font-weight: bold; font-size: 14px;">{{ $t('billing.totalAmount') }}{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}{{ $t('billing.yuan') }}</span>
</div>
<vxe-table
ref="chargeListRef"
@@ -201,40 +201,40 @@
width="55"
/>
<vxe-column
title="单据号"
:title="$t('billing.docNo')"
align="center"
field="busNo"
width="180"
/>
<vxe-column
title="收费项目"
:title="$t('billing.chargeItems')"
align="center"
field="itemName"
width="200"
/>
<vxe-column
title="数量"
:title="$t('billing.quantity')"
align="center"
field="quantityValue"
width="80"
/>
<vxe-column
title="医疗类型"
:title="$t('billing.medicalType')"
align="center"
field="medTypeCode_dictText"
/>
<vxe-column
title="医保编码"
:title="$t('billing.insuranceCode')"
align="center"
field="ybNo"
/>
<vxe-column
title="费用性质"
:title="$t('billing.feeNature')"
align="center"
field="contractName"
/>
<vxe-column
title="收费状态"
:title="$t('billing.chargeStatus')"
align="center"
field="statusEnum_enumText"
width="150"
@@ -270,22 +270,22 @@
</template>
</vxe-column>
<vxe-column
title="金额"
:title="$t('billing.amount')"
align="right"
field="totalPrice"
header-align="center"
>
<template #default="scope">
{{ scope.row.totalPrice.toFixed(2) + ' 元' || '0.00' + ' 元' }}
{{ scope.row.totalPrice.toFixed(2) + ' ' + $t('billing.yuan') || '0.00' + ' ' + $t('billing.yuan') }}
</template>
</vxe-column>
<vxe-column
title="收款人"
:title="$t('billing.cashier')"
align="center"
field="entererId_dictText"
/>
<vxe-column
title="操作"
:title="$t('billing.operation')"
align="center"
fixed="right"
header-align="center"
@@ -298,7 +298,7 @@
type="primary"
@click="printCharge(scope.row)"
>
打印
{{ $t('billing.print') }}
</el-button>
</template>
</vxe-column>
@@ -344,7 +344,9 @@ import ChargeDialog from './components/chargeDialog.vue';
import {formatDateStr} from '@/utils';
import useUserStore from '@/store/modules/user';
import Decimal from 'decimal.js';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const { medfee_paymtd_code } = proxy.useDict('medfee_paymtd_code');
@@ -368,7 +370,13 @@ const openDialog = ref(false);
const totalAmount = ref(0);
const chargeListRef = ref();
const details = ref({});
const chargeStatusOptions = ref([]);
const chargeStatusOptionsRaw = ref([]);
const chargeStatusOptions = computed(() => {
return (chargeStatusOptionsRaw.value || []).map(item => ({
value: item.value,
label: item.label ? t('billing.' + item.label, item.label) : item.label,
}));
});
const receptionTime = ref([
formatDateStr(new Date(), 'YYYY-MM-DD'),
formatDateStr(new Date(), 'YYYY-MM-DD'),
@@ -435,7 +443,7 @@ function getPatientList() {
function initOption() {
init().then((res) => {
chargeStatusOptions.value = res.data.chargeItemStatusOptions;
chargeStatusOptionsRaw.value = res.data.chargeItemStatusOptions;
});
}
@@ -487,7 +495,7 @@ const consumablesIdList = ref([]);
function confirmCharge() {
let selectRows = chargeListRef.value.getSelectionRows();
if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目');
proxy.$modal.msgWarning(t('billing.selectChargeItem'));
return;
}
chargeItemIdList.value = selectRows.map((item) => {
@@ -523,7 +531,7 @@ function confirmCharge() {
}) || [];
openDialog.value = true;
} else {
proxy.$modal.msgError(res?.msg || '预结算失败');
proxy.$modal.msgError(res?.msg || t('billing.preSettleFail'));
}
});
// console.log(patientInfo)
@@ -566,7 +574,7 @@ async function handleReadCard(value) {
})
.then((res) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
loadingText.value = t('billing.reading');
jsonResult = res.data;
})
.catch(() => {
@@ -578,24 +586,24 @@ async function handleReadCard(value) {
cardInfo = JSON.parse(JSON.stringify(jsonResult));
let message = JSON.parse(cardInfo.data);
userMessage = {
certType: '02', // 证件类型
certNo: message.data.idNo, // 身份证号
psnCertType: '02', // 居民身份证
certType: '02',
certNo: message.data.idNo,
psnCertType: '02',
};
userCardInfo = {
certType: '01', // 证件类型
certNo: message.data.idNo, // 身份证号
psnCertType: '01', // 居民身份证
busiCardInfo: message.data.ecToken, // 令牌
certType: '01',
certNo: message.data.idNo,
psnCertType: '01',
busiCardInfo: message.data.ecToken,
};
BusiCardInfo.value = message.data.ecToken;
console.log(BusiCardInfo.value);
break;
case '02':
break;
case '03': // 社保卡
case '03':
readCardLoading.value = true;
loadingText.value = '正在读取...';
loadingText.value = t('billing.reading');
await invokeYbPlugin5001(
JSON.stringify({
FunctionId: 1,
@@ -651,7 +659,7 @@ async function handleReadCard(value) {
if (userMessage.certNo) {
let selectRows = chargeListRef.value.getSelectionRows();
if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目');
proxy.$modal.msgWarning(t('billing.selectChargeItem'));
return;
}
chargeItemIdList.value = selectRows.map((item) => {
@@ -687,7 +695,7 @@ async function handleReadCard(value) {
});
openDialog.value = true;
} else {
proxy.$modal.msgError(res?.msg || '预结算失败');
proxy.$modal.msgError(res?.msg || t('billing.preSettleFail'));
}
});
}
@@ -704,7 +712,7 @@ async function handleReadCard(value) {
function payToSelt() {
changeToSelfPay(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('billing.opSuccess'));
}
});
}
@@ -715,7 +723,7 @@ function payToSelt() {
function patToMedicalInsurance() {
changeToMedicalInsurance(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('billing.opSuccess'));
}
});
}
@@ -726,7 +734,7 @@ function patToMedicalInsurance() {
function studentPayTosStudentSelf() {
changeStudentPayTosStudentSelf(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('billing.opSuccess'));
}
});
}
@@ -737,7 +745,7 @@ function studentPayTosStudentSelf() {
function studentSelfToStudentPay() {
changeStudentSelfToStudentPay(encounterId.value).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('billing.opSuccess'));
}
});
}

View File

@@ -1,7 +1,7 @@
<template>
<template>
<el-dialog
v-model="props.open"
title="确认退费"
:title="$t('billing.refundConfirm')"
width="700px"
teleported
destroy-on-close
@@ -12,21 +12,21 @@
size="large"
style="display: block; margin-bottom: 15px"
>
退费日期{{ currentDate }}
{{ $t('billing.refundDate') + '' }}{{ currentDate }}
</el-text>
<el-text size="large">
费用性质{{ getFeeTypeText }}
{{ $t('billing.feeNature') + '' }}{{ getFeeTypeText }}
</el-text>
<div class="amount-row">
<el-text size="large">
应退金额
{{ $t('billing.refundAmount') + '' }}
</el-text>
<el-text
size="large"
type="primary"
class="amount"
>
{{ props.totalAmount.toFixed(2) + ' ' }}
{{ props.totalAmount.toFixed(2) + ' ' + $t('billing.yuan') }}
</el-text>
</div>
@@ -37,10 +37,10 @@
:key="index"
class="payment-item"
>
<span>退费方式</span>
<span>{{ $t('billing.refundMethod') + '' }}</span>
<el-select
v-model="item.payEnum"
placeholder="选择退费方式"
:placeholder="$t('billing.selectRefundMethod')"
style="width: 160px"
@change="clearAmount(index)"
>
@@ -52,7 +52,7 @@
:disabled="isMethodDisabled(payEnum.value)"
/>
</el-select>
<span>退费金额</span>
<span>{{ $t('billing.refundAmountLabel') + '' }}</span>
<div class="suffix-wrapper">
<el-input-number
v-model="item.amount"
@@ -64,7 +64,7 @@
class="amount-input"
@change="handleAmountChange"
/>
<span class="suffix-text"></span>
<span class="suffix-text">{{ $t('billing.yuan') }}</span>
</div>
<el-button
v-if="index > 0"
@@ -78,12 +78,12 @@
class="payment-container"
style="position: relative"
>
<span style="position: absolute; top: 5px">退费原因</span>
<span style="position: absolute; top: 5px">{{ $t('billing.refundReason') + '' }}</span>
<el-input
v-model="reason"
type="textarea"
:rows="2"
placeholder="退费原因"
:placeholder="$t('billing.refundReason')"
class="reason-textarea"
@change="handleAmountChange"
/>
@@ -95,14 +95,14 @@
:disabled="formData.selfPay.length >= 4 || remainingAmount <= 0"
@click="addPayment"
>
添加退费方式
{{ $t('billing.addRefundMethod') }}
</el-button>
<el-text
v-if="remainingAmount <= 0"
type="danger"
class="tip"
>
金额已满足应退不可继续添加
{{ $t('billing.refundAmountSatisfied') }}
</el-text>
</div>
</div>
@@ -114,18 +114,18 @@
>
<vxe-column
field="payEnum_dictText"
title="支付类型"
:title="$t('billing.payType')"
align="center"
/>
<vxe-column
field="amount"
title="金额"
:title="$t('billing.amount')"
header-align="center"
align="right"
width="200"
>
<template #default="scope">
{{ scope.row.amount ? scope.row.amount + ' ' : '-' }}
{{ scope.row.amount ? scope.row.amount + ' ' + $t('billing.yuan') : '-' }}
</template>
</vxe-column>
</vxe-table>
@@ -135,10 +135,10 @@
<el-space :size="30">
<div class="summary-item">
<el-text type="info">
实退合计
{{ $t('billing.refundTotal') + '' }}
</el-text>
<el-text type="success">
{{ displayAmount + ' ' }}
{{ displayAmount + ' ' + $t('billing.yuan') }}
</el-text>
</div>
<!-- <div class="summary-item">
@@ -154,10 +154,10 @@
type="primary"
@click="submit"
>
{{ $t('billing.confirm') }}
</el-button>
<el-button @click="close">
{{ $t('billing.cancel') }}
</el-button>
</div>
</template>
@@ -167,6 +167,8 @@
<script setup>
import {getReturnMedicineList, refund, renturnDispenseMedical} from './api';
import {computed, getCurrentInstance, reactive, ref, watch} from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
import {Delete} from '@element-plus/icons-vue';
import useUserStore from '@/store/modules/user';
@@ -247,7 +249,7 @@ function submit() {
);
//比较时,将金额都转换为两位小数的字符串再转换为浮点数,避免浮点数精度问题
if (parseFloat(displayAmount.value) < parseFloat(formData.totalAmount.toFixed(2))) {
proxy.$modal.msgError('请输入正确的金额');
proxy.$modal.msgError(t('billing.enterCorrectRefundAmount'));
return;
}
if (userStore.fixmedinsCode == '1123123') {
@@ -313,12 +315,12 @@ function submit() {
const currentDate = ref(new Date().toLocaleString());
const selfPayMethods = [
{ label: '现金', value: 220400 },
{ label: '微信', value: 220100 },
{ label: '支付宝', value: 220200 },
{ label: '银联', value: 220300 },
];
const selfPayMethods = computed(() => [
{ label: t('billing.cash'), value: 220400 },
{ label: t('billing.wechat'), value: 220100 },
{ label: t('billing.alipay'), value: 220200 },
{ label: t('billing.unionpay'), value: 220300 },
]);
// 计算剩余可输入金额
const remainingAmount = computed(() => {
@@ -384,18 +386,18 @@ function close() {
// 获取费用性质文本
const getFeeTypeText = computed(() => {
if (!props.medfee_paymtd_code || !Array.isArray(props.medfee_paymtd_code)) {
return '自费';
return t('billing.selfPay');
}
// 如果有feeType根据feeType查找对应的文本
if (props.feeType) {
const dict = props.medfee_paymtd_code.find(item => item.value === props.feeType);
return dict ? dict.label : '自费';
return dict ? dict.label : t('billing.selfPay');
}
// 如果只有一个选项,直接返回第一个选项的文本
if (props.medfee_paymtd_code.length === 1) {
return props.medfee_paymtd_code[0].label || '自费';
return props.medfee_paymtd_code[0].label || t('billing.selfPay');
}
return '自费';
return t('billing.selfPay');
});
</script>

View File

@@ -1,16 +1,16 @@
<template>
<template>
<div
style="display: flex; justify-content: space-between"
class="app-container"
>
<el-card style="width: 30%">
<template #header>
<span style="vertical-align: middle">患者列表</span>
<span style="vertical-align: middle">{{ $t('billing.patientList') }}</span>
</template>
<div style="width: 100%">
<el-input
v-model="queryParams.patientName"
placeholder="请输入患者名"
:placeholder="$t('billing.searchPlaceholderName')"
clearable
style="width: 49%; margin-bottom: 10px; margin-right: 10px"
@keyup.enter="getPatientList"
@@ -25,7 +25,7 @@
<el-select
v-model="queryParams.statusEnum"
style="width: 49%; margin-bottom: 10px"
placeholder="收费状态"
:placeholder="$t('billing.chargeStatus')"
@change="getPatientList"
>
<el-option
@@ -39,8 +39,8 @@
v-model="maxBillDate"
type="daterange"
range-separator="~"
start-placeholder="开始时间"
end-placeholder="结束时间"
:start-placeholder="$t('billing.startTime')"
:end-placeholder="$t('billing.endTime')"
placement="bottom"
:clearable="false"
value-format="YYYY-MM-DD"
@@ -51,7 +51,7 @@
style="margin-bottom: 10px"
@click="getPatientList"
>
搜索
{{ $t('billing.search') }}
</el-button>
<vxe-table
ref="patientListRef"
@@ -62,12 +62,12 @@
@cell-click="clickRow"
>
<vxe-column
title="病历号"
:title="$t('billing.medicalRecordNo')"
align="center"
field="encounterBusNo"
/>
<vxe-column
title="姓名"
:title="$t('billing.name')"
align="center"
field="patientName"
/>
@@ -77,7 +77,7 @@
</template>
</vxe-column> -->
<vxe-column
title="收费状态"
:title="$t('billing.chargeStatus')"
align="center"
field="statusEnum_enumText"
/>
@@ -87,19 +87,19 @@
<div style="width: 69%">
<el-card style="margin-bottom: 20px; height: 15%">
<template #header>
<span style="vertical-align: middle">基本信息</span>
<span style="vertical-align: middle">{{ $t('billing.basicInfo') }}</span>
</template>
<el-descriptions :column="4">
<el-descriptions-item label="就诊号:">
<el-descriptions-item :label="$t('billing.encounterNo') + ':'">
{{ patientInfo.encounterId }}
</el-descriptions-item>
<el-descriptions-item label="姓名:">
<el-descriptions-item :label="$t('billing.name') + ':'">
{{ patientInfo.patientName }}
</el-descriptions-item>
<el-descriptions-item label="性别:">
<el-descriptions-item :label="$t('billing.gender') + ':'">
{{ patientInfo.genderEnum_enumText }}
</el-descriptions-item>
<el-descriptions-item label="年龄:">
<el-descriptions-item :label="$t('billing.age') + ':'">
{{ patientInfo.age }}
</el-descriptions-item>
<!-- <el-descriptions-item label="合同类型:">
@@ -129,7 +129,7 @@
</el-card>
<el-card style="height: 83%">
<template #header>
<span style="vertical-align: middle">退费单据</span>
<span style="vertical-align: middle">{{ $t('billing.refundDocs') }}</span>
</template>
<!-- <el-button type="primary" @click="handleRefund()" :disabled="buttonDisabled">
确认退费
@@ -146,7 +146,7 @@
>
<!-- <vxe-column type="checkbox" :selectable="checkSelectable" width="55" /> -->
<vxe-column
title="操作"
:title="$t('billing.operation')"
align="center"
>
<template #default="scope">
@@ -155,34 +155,34 @@
type="primary"
@click="handleRefund(scope.row)"
>
退费
{{ $t('billing.refundItem') }}
</el-button>
</template>
</vxe-column>
<vxe-column
field="paymentId"
title="支付单据号"
:title="$t('billing.refundDocNo')"
align="center"
/>
<vxe-column
title="项目单据号"
:title="$t('billing.itemDocNo')"
align="center"
field="busNo"
width="150"
/>
<vxe-column
title="项目名称"
:title="$t('billing.itemNameCol')"
align="center"
field="itemName"
/>
<vxe-column
title="收费状态"
:title="$t('billing.chargeStatusCol')"
align="center"
field="chargeStatus_enumText"
width="100"
/>
<vxe-column
title="数量"
:title="$t('billing.quantity')"
align="center"
width="100"
>
@@ -191,19 +191,19 @@
</template>
</vxe-column>
<vxe-column
title="付款总额"
:title="$t('billing.paymentTotal')"
align="right"
field="totalPrice"
header-align="center"
width="100"
>
<template #default="scope">
{{ scope.row.totalPrice.toFixed(2) + ' ' }}
{{ scope.row.totalPrice.toFixed(2) + ' ' + $t('billing.yuan') }}
</template>
</vxe-column>
<!-- <vxe-column title="处方号" align="center" field="prescriptionNo" /> -->
<vxe-column
title="收款人"
:title="$t('billing.cashier')"
align="center"
field="entererName"
width="120"
@@ -226,6 +226,8 @@
</template>
<script setup name="ClinicCharge">
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
import {getChargeItemIds, getList, getRefundList, getReturnDetail, init, validReturnDrug,} from './components/api';
import {formatDateStr} from '@/utils/index';
import RefundDialog from './components/refundDialog.vue';
@@ -389,7 +391,7 @@ function handleRefund(row) {
function handleClose(value) {
openDialog.value = false;
if (value == 'success') {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('billing.opSuccess'));
clickRow(patientInfo.value);
}
}

View File

@@ -1,7 +1,7 @@
<template>
<el-dialog
v-model="props.open"
title="确认收费"
:title="$t('billing.confirmCharge')"
width="700px"
teleported
destroy-on-close
@@ -12,21 +12,21 @@
size="large"
style="display: block; margin-bottom: 15px"
>
收费日期{{ currentDate }}
{{ $t('billing.chargeDate') }}{{ currentDate }}
</el-text>
<el-text size="large">
费用性质{{ getFeeTypeText }}
{{ $t('billing.feeNature') }}{{ getFeeTypeText }}
</el-text>
<div class="amount-row">
<el-text size="large">
应收金额
{{ $t('billing.receivableAmount') }}
</el-text>
<el-text
size="large"
type="primary"
class="amount"
>
{{ props.totalAmount.toFixed(2) + ' ' }}
{{ props.totalAmount.toFixed(2) + ' ' + $t('billing.yuan') }}
</el-text>
</div>
@@ -37,10 +37,10 @@
:key="index"
class="payment-item"
>
<span>支付方式</span>
<span>{{ $t('billing.payMethod') }}</span>
<el-select
v-model="item.payEnum"
placeholder="选择支付方式"
:placeholder="$t('billing.selectPayMethod')"
style="width: 160px"
@change="clearAmount(index)"
>
@@ -52,7 +52,7 @@
:disabled="isMethodDisabled(payEnum)"
/>
</el-select>
<span>支付金额</span>
<span>{{ $t('billing.payAmount') }}</span>
<div class="suffix-wrapper">
<el-input-number
v-model="item.amount"
@@ -60,11 +60,11 @@
:min="0"
:max="getMax(index)"
:controls="false"
placeholder="金额"
:placeholder="$t('billing.amount')"
class="amount-input"
@change="handleAmountChange"
/>
<span class="suffix-text"></span>
<span class="suffix-text">{{ $t('billing.yuan') }}</span>
</div>
<el-button
v-if="index > 0"
@@ -81,19 +81,19 @@
:disabled="formData.selfPay.length >= 4 || remainingAmount <= 0"
@click="addPayment"
>
添加支付方式
{{ $t('billing.addPayMethod') }}
</el-button>
<el-text
v-if="remainingAmount <= 0"
type="danger"
class="tip"
>
金额已满足应收不可继续添加
{{ $t('billing.amountSatisfied') }}
</el-text>
</div>
</div>
<div class="payment-item">
<span>{{ payTypeText }}支付</span>
<span>{{ payTypeText + $t('billing.payMethod') }}</span>
<el-input
ref="txtCodeRef"
v-model="txtCode"
@@ -105,14 +105,14 @@
type="primary"
@click="handleWxPay()"
>
扫码支付
{{ $t('billing.wechatPay') }}
</el-button>
<el-button
link
type="primary"
@click="getWxPayResult()"
>
查看结果
{{ $t('billing.viewResult') }}
</el-button>
</div>
<!-- 金额汇总 -->
@@ -120,18 +120,18 @@
<el-space :size="30">
<div class="summary-item">
<el-text type="info">
实收合计
{{ $t('billing.actualTotal') }}
</el-text>
<el-text type="success">
{{ displayAmount + ' ' }}
{{ displayAmount + ' ' + $t('billing.yuan') }}
</el-text>
</div>
<div class="summary-item">
<el-text type="info">
应找零
{{ $t('billing.changeAmount') }}
</el-text>
<el-text type="warning">
{{ returnedAmount + ' ' }}
{{ returnedAmount + ' ' + $t('billing.yuan') }}
</el-text>
</div>
</el-space>
@@ -144,13 +144,13 @@
:disabled="dialogLoading"
@click="throttledGetList"
>
{{ $t('billing.confirm') }}
</el-button>
<el-button
:disabled="dialogLoading"
@click="close"
>
{{ $t('billing.cancel') }}
</el-button>
</div>
</template>
@@ -162,8 +162,11 @@ import {savePayment, wxPay, WxPayResult} from './outpatientregistration';
import {computed, getCurrentInstance, nextTick, reactive, ref, watch} from 'vue';
import {Delete} from '@element-plus/icons-vue';
import {debounce} from 'lodash-es';
import {useI18n} from 'vue-i18n';
import printUtils, {PRINT_TEMPLATE, printRegistrationReceipt} from '@/utils/printUtils';
const { t } = useI18n();
// 获取费用性质文本
const getFeeTypeText = computed(() => {
if (!props.medfee_paymtd_code || !Array.isArray(props.medfee_paymtd_code)) {
@@ -282,7 +285,7 @@ async function printReceipt(param) {
console.log('打印成功');
} catch (error) {
console.error('打印失败:', error);
proxy.$modal.msgError('打印失败:' + error.message);
proxy.$modal.msgError(t('billing.printFail') + ': ' + error.message);
}
}
function handleWxPay() {
@@ -322,7 +325,7 @@ function getWxPayResult() {
function submit() {
if (parseFloat(displayAmount.value) < formData.totalAmount) {
proxy.$modal.msgError('请输入正确的结算金额');
proxy.$modal.msgError(t('billing.enterCorrectAmount'));
return;
}
dialogLoading.value = true;
@@ -352,12 +355,12 @@ function submit() {
const currentDate = ref(new Date().toLocaleString());
const selfPayMethods = [
{ label: '现金', value: 220400, isWebPay: false },
{ label: '微信', value: 220100, isWebPay: true },
{ label: '支付宝', value: 220200, isWebPay: true },
{ label: '银联', value: 220300, isWebPay: true },
];
const selfPayMethods = computed(() => [
{ label: t('billing.cash'), value: 220400, isWebPay: false },
{ label: t('billing.wechat'), value: 220100, isWebPay: true },
{ label: t('billing.alipay'), value: 220200, isWebPay: true },
{ label: t('billing.unionpay'), value: 220300, isWebPay: true },
]);
// 计算剩余可输入金额
const remainingAmount = computed(() => {
@@ -389,7 +392,7 @@ const isMethodDisabled = (option) => {
}
// 若已经选择了任一线上支付方式,则其他线上方式不可再选,仅允许现金等线下方式
const hasSelectedWebPay = selectedEnums.some((val) => {
const found = selfPayMethods.find((m) => m.value === val);
const found = selfPayMethods.value.find((m) => m.value === val);
return found ? found.isWebPay === true : false;
});
if (hasSelectedWebPay && option.isWebPay) {
@@ -414,16 +417,16 @@ const addPayment = () => {
const removePayment = (index) => {
formData.selfPay.splice(index, 1);
};
const payTypeText = ref('微信');
const payTypeText = ref(t('billing.wechat'));
const payTypePlaceholder = computed(() => {
if (payTypeText.value === '现金') {
if (payTypeText.value === t('billing.cash')) {
return '请输入现金金额';
}
return payTypeText.value + '支付二维码';
});
const clearAmount = (index) => {
// formData.selfPay[index].amount = 0;
const selectedOption = selfPayMethods.find(
const selectedOption = selfPayMethods.value.find(
(item) => item.value === formData.selfPay[index].payEnum
);
if (selectedOption) {

View File

@@ -1,4 +1,4 @@
<template>
<template>
<!-- <div class="app-container"> -->
<el-dialog
v-model="visible"
@@ -19,28 +19,28 @@
/>
<vxe-column
key="name"
title="患者姓名"
:title="$t('billing.patientName')"
align="center"
field="name"
show-overflow="title"
/>
<vxe-column
key="genderEnum_enumText"
title="性别"
:title="$t('billing.gender')"
align="center"
field="genderEnum_enumText"
show-overflow="title"
/>
<vxe-column
key="idCard"
title="身份证号"
:title="$t('registration.idCardNo')"
align="center"
field="idCard"
show-overflow="title"
/>
<vxe-column
key="phone"
title="电话"
:title="$t('registration.phone')"
align="center"
field="phone"
show-overflow="title"
@@ -48,7 +48,7 @@
/>
<vxe-column
key="birthDate"
title="生日"
:title="$t('billing.birthDate')"
align="center"
field="birthDate"
show-overflow="title"
@@ -56,12 +56,12 @@
/>
<vxe-column
key="age"
title="年龄"
:title="$t('billing.age')"
align="center"
show-overflow="title"
>
<template #default="scope">
{{ scope.row.age ? `${scope.row.age}` : '-' }}
{{ scope.row.age ? `${scope.row.age}` : '-' }}
</template>
</vxe-column>
</vxe-table>
@@ -78,10 +78,10 @@
type="primary"
@click="submitForm"
>
{{ $t('billing.confirm') }}
</el-button>
<el-button @click="cancel">
{{ $t('billing.cancel') }}
</el-button>
</div>
</template>
@@ -91,7 +91,9 @@
<script setup name="PatientInfoDialog">
import {getOutpatientRegistrationList,} from "./outpatientregistration";
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
@@ -100,7 +102,7 @@ const selectedData = ref([]); // 存储选择的行数据
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("病人信息");
const title = ref(t('billing.patientArchiveQuery'));
const visible = ref(false);
const emits = defineEmits(['submit']); // 声明自定义事件
@@ -170,7 +172,7 @@ function cancel() {
/** 提交按钮 */
function submitForm() {
if (selectedData.value.length > 1) {
proxy.$modal.msgSuccess("只能选中一条数据操作!");
proxy.$modal.msgSuccess(t('billing.opSuccess'));
} else if (selectedData.value.length === 1) {
console.log(selectedData.value[0], "selectedData.value");
const data = selectedData.value[0];

View File

@@ -8,37 +8,37 @@
@cell-click="clickRow"
>
<vxe-column
title="姓名"
:title="$t('billing.name')"
align="center"
field="name"
:min-width="80"
/>
<vxe-column
title="就诊卡号"
:title="$t('registration.cardNo')"
align="center"
field="identifierNo"
:min-width="140"
/>
<vxe-column
title="性别"
:title="$t('billing.gender')"
align="center"
field="genderEnum_enumText"
:min-width="60"
/>
<vxe-column
title="证件号"
:title="$t('registration.idCardNo')"
align="center"
field="idCard"
:min-width="180"
/>
<vxe-column
title="联系电话"
:title="$t('registration.phone')"
align="center"
field="phone"
:min-width="130"
/>
<vxe-column
title="年龄"
:title="$t('billing.age')"
align="center"
:min-width="60"
>
@@ -52,6 +52,9 @@
<script setup>
import {getOutpatientRegistrationList} from "./outpatientregistration";
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const props = defineProps({
searchkey: {

View File

@@ -1,7 +1,7 @@
<template>
<template>
<el-dialog
v-model="props.open"
:title="eventType == '1' ? '确认退费' : '挂号详情'"
:title="eventType == '1' ? $t('billing.refundConfirm') : $t('registration.detail')"
width="700px"
teleported
destroy-on-close
@@ -12,21 +12,21 @@
size="large"
style="display: block; margin-bottom: 15px"
>
退费日期{{ currentDate }}
{{ $t('billing.refundDate') + '' }}{{ currentDate }}
</el-text>
<el-text size="large">
费用性质{{ props.category || '自费' }}
{{ $t('billing.feeNature') + '' }}{{ props.category || $t('billing.selfPay') }}
</el-text>
<div class="amount-row">
<el-text size="large">
应退金额
{{ $t('billing.refundAmount') + '' }}
</el-text>
<el-text
size="large"
type="primary"
class="amount"
>
{{ (calculatedTotalAmount || 0) + ' ' }}
{{ (calculatedTotalAmount || 0) + ' ' + $t('billing.yuan') }}
</el-text>
</div>
<div
@@ -34,14 +34,14 @@
class="amount-row"
>
<el-text size="large">
退费金额
{{ $t('billing.refundAmountLabel') + '' }}
</el-text>
<el-text
size="large"
type="primary"
class="amount"
>
{{ (calculatedReturnAmount || 0) + ' ' }}
{{ (calculatedReturnAmount || 0) + ' ' + $t('billing.yuan') }}
</el-text>
</div>
@@ -52,13 +52,13 @@
:key="index"
class="payment-item"
>
<span>退费方式</span>
<span>{{ $t('billing.refundMethod') + '' }}</span>
<el-input
:value="getPayMethodLabel(item.payEnum)"
readonly
style="width: 160px"
/>
<span>退费金额</span>
<span>{{ $t('billing.refundAmountLabel') + '' }}</span>
<div class="suffix-wrapper">
<el-input-number
:model-value="(Number(item.amount) || 0) - (Number(item.returnAmount) || 0)"
@@ -67,19 +67,19 @@
disabled
class="amount-input"
/>
<span class="suffix-text"></span>
<span class="suffix-text">{{ $t('billing.yuan') }}</span>
</div>
</div>
<div
class="payment-container"
style="position: relative"
>
<span style="position: absolute; top: 5px">退费原因</span>
<span style="position: absolute; top: 5px">{{ $t('billing.refundReason') + '' }}</span>
<el-input
v-model="reason"
type="textarea"
:rows="2"
placeholder="退费原因"
:placeholder="$t('billing.refundReason')"
class="reason-textarea"
:disabled="eventType == '1' ? false : true"
/>
@@ -99,11 +99,11 @@
<el-space :size="30">
<div class="summary-item">
<el-text type="info">
实退合计
{{ $t('billing.refundTotal') + '' }}
</el-text>
<el-text type="success">
{{
displayAmount > 0 ? displayAmount + ' ' : props.totalAmount + ' '
displayAmount > 0 ? displayAmount + ' ' + $t('billing.yuan') : props.totalAmount + ' ' + $t('billing.yuan')
}}
</el-text>
</div>
@@ -128,12 +128,12 @@
>
<vxe-column
field="payEnum_dictText"
title="支付方式"
:title="$t('billing.payMethod')"
min-width="200"
/>
<vxe-column
field="amount"
title="金额"
:title="$t('billing.amount')"
width="120"
align="right"
>
@@ -143,7 +143,7 @@
</vxe-column>
<vxe-column
field="returnAmount"
title="退费金额"
:title="$t('billing.refundAmountLabel')"
width="120"
align="right"
>
@@ -153,7 +153,7 @@
</vxe-column>
<vxe-column
field="chargeAmount"
title="收费金额"
:title="$t('billing.amount')"
min-width="120"
align="right"
>
@@ -171,10 +171,10 @@
type="primary"
@click="submit"
>
{{ $t('billing.confirm') }}
</el-button>
<el-button @click="close">
{{ $t('billing.cancel') }}
</el-button>
</div>
</template>
@@ -184,7 +184,9 @@
<script setup>
import {cancelRegister, preCancelReg} from './outpatientregistration';
import {computed, getCurrentInstance, reactive, ref, watch} from 'vue';
import { useI18n } from 'vue-i18n';
import useUserStore from '@/store/modules/user.js'
const { t } = useI18n();
//获取当前登陆用户的信息
const userStore = useUserStore();
@@ -198,10 +200,10 @@ const getFeeTypeText = computed(() => {
// 如果没有传递名称,则根据费用性质代码查找
if (props.feeType && props.medfee_paymtd_code && Array.isArray(props.medfee_paymtd_code)) {
const dictItem = props.medfee_paymtd_code.find(item => item.value === props.feeType);
return dictItem ? dictItem.label : '自费';
return dictItem ? dictItem.label : t('billing.selfPay');
}
return '自费'; // 默认值
return t('billing.selfPay'); // 默认值
});
const props = defineProps({
@@ -336,12 +338,12 @@ function submit() {
const currentDate = ref(new Date().toLocaleString());
const selfPayMethods = [
{ label: '现金', value: 220400 },
{ label: '微信', value: 220100 },
{ label: '支付宝', value: 220200 },
{ label: '银联', value: 220300 },
];
const selfPayMethods = computed(() => [
{ label: t('billing.cash'), value: 220400 },
{ label: t('billing.wechat'), value: 220100 },
{ label: t('billing.alipay'), value: 220200 },
{ label: t('billing.unionpay'), value: 220300 },
]);
const getMax = (index) => {
const otherSum = formData.selfPay.reduce(
@@ -443,13 +445,13 @@ const refundMethodsFromApi = computed(() => {
// 根据 payEnum 获取支付方式标签
const getPayMethodLabel = (payEnum) => {
const method = selfPayMethods.find((m) => m.value === payEnum);
const method = selfPayMethods.value.find((m) => m.value === payEnum);
if (method) {
return method.label;
}
// 如果找不到,尝试从接口返回的 dictText 中获取
const apiItem = preCancelData.value?.find((item) => item.payEnum === payEnum);
return apiItem?.payEnum_dictText || `支付方式${payEnum}`;
return apiItem?.payEnum_dictText || t('billing.payMethod') + payEnum;
};
// 计算所有退费方式的总和

View File

@@ -1,7 +1,7 @@
<template>
<el-dialog
v-model="dialogVisible"
title="补打挂号单凭证"
:title="$t('billing.reprintRegistration')"
width="900px"
teleported
destroy-on-close
@@ -14,10 +14,10 @@
<!-- 标题区域 -->
<div style="text-align: center; margin-bottom: 20px;">
<h2 style="color: #ff0000; font-size: 24px; font-weight: bold; margin: 0 0 10px 0;">
挂号单重打
{{ $t('billing.reprintTitle') }}
</h2>
<p style="color: #ff0000; font-size: 14px; margin: 0;">
补打挂号单将作废原有的挂号单据并生成新的挂号单据
{{ $t('billing.reprintSubtitle') }}
</p>
</div>
@@ -32,52 +32,52 @@
<!-- 左列 -->
<el-col :span="12">
<el-form-item
label="病人姓名:"
:label="$t('billing.patientName') + ''"
prop="name"
>
<el-input
v-model="form.name"
placeholder="病人姓名"
:placeholder="$t('billing.patientName')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="医生姓名:"
:label="$t('billing.doctorName') + ''"
prop="practitionerName"
>
<el-input
v-model="form.practitionerName"
placeholder="医生姓名"
:placeholder="$t('billing.doctorName')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="诊疗费:"
:label="$t('registration.consultationFeeLabel')"
prop="activityPrice"
>
<el-input
v-model="form.activityPrice"
placeholder="诊疗费"
:placeholder="$t('registration.consultationFee')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="流水号:"
:label="$t('billing.serialNo') + ''"
prop="serialNo"
>
<el-input
v-model="form.serialNo"
placeholder="流水号"
:placeholder="$t('billing.serialNo')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="合计:"
:label="$t('billing.totalLabel') + ''"
prop="totalPrice"
>
<el-input
v-model="form.totalPrice"
placeholder="合计"
:placeholder="$t('billing.totalLabel')"
:disabled="true"
/>
</el-form-item>
@@ -86,42 +86,42 @@
<!-- 右列 -->
<el-col :span="12">
<el-form-item
label="挂号科室:"
:label="$t('registration.registrationDepartmentLabel')"
prop="organizationName"
>
<el-input
v-model="form.organizationName"
placeholder="挂号科室"
:placeholder="$t('registration.registrationDepartment')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="挂号费:"
:label="$t('registration.registrationFeeLabel')"
prop="price"
>
<el-input
v-model="form.price"
placeholder="挂号费"
:placeholder="$t('registration.registrationFee')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="病历费:"
:label="$t('billing.medicalRecordFee') + ''"
prop="medicalRecordFee"
>
<el-input
v-model="form.medicalRecordFee"
placeholder="病历费"
:placeholder="$t('billing.medicalRecordFee')"
:disabled="true"
/>
</el-form-item>
<el-form-item
label="打印时间:"
:label="$t('billing.printTime') + ''"
prop="printTime"
>
<el-input
v-model="form.printTime"
placeholder="打印时间"
:placeholder="$t('billing.printTime')"
:disabled="true"
/>
</el-form-item>
@@ -132,12 +132,12 @@
<el-row>
<el-col :span="24">
<el-form-item
label="预约/挂号时间:"
:label="$t('billing.visitTimeLabel') + ''"
prop="visitTime"
>
<el-input
v-model="form.visitTime"
placeholder="预约/挂号时间"
:placeholder="$t('billing.visitTimeLabel')"
:disabled="true"
/>
</el-form-item>
@@ -152,12 +152,12 @@
style="margin: 0;"
>
<el-form-item
label="就诊卡号:"
:label="$t('registration.cardNoLabel')"
style="margin-bottom: 0;"
>
<el-input
v-model="searchForm.cardNo"
placeholder="请输入就诊卡号检索条"
:placeholder="$t('billing.enterCardNoSearch')"
style="width: 300px; margin-right: 10px;"
clearable
@keyup.enter="handleSearch"
@@ -167,10 +167,10 @@
:loading="loading"
@click="handleSearch"
>
确认(O)
{{ $t('billing.confirmSelect') }}
</el-button>
<el-button @click="handleCancel">
取消(C)
{{ $t('billing.cancel') }}
</el-button>
</el-form-item>
</el-form>
@@ -180,7 +180,7 @@
<!-- 挂号记录选择对话框 -->
<el-dialog
v-model="selectDialogVisible"
title="挂号记录选择"
:title="$t('billing.regRecordSelect')"
width="800px"
teleported
:close-on-click-modal="false"
@@ -193,13 +193,13 @@
@current-change="handleRecordSelect"
>
<vxe-column
title="序号"
:title="$t('billing.seqNo')"
type="seq"
width="60"
align="center"
/>
<vxe-column
title="挂号时间"
:title="$t('registration.registrationTime')"
field="registerTime"
width="180"
align="center"
@@ -209,7 +209,7 @@
</template>
</vxe-column>
<vxe-column
title="挂号科室"
:title="$t('registration.registrationDepartment')"
field="organizationName"
align="center"
>
@@ -218,7 +218,7 @@
</template>
</vxe-column>
<vxe-column
title="医生姓名"
:title="$t('billing.doctorName')"
field="practitionerName"
align="center"
>
@@ -227,7 +227,7 @@
</template>
</vxe-column>
<vxe-column
title="流水号"
:title="$t('billing.serialNo')"
field="encounterNo"
align="center"
>
@@ -239,14 +239,14 @@
<template #footer>
<div class="dialog-footer">
<el-button @click="selectDialogVisible = false">
取消 (C)
{{ $t('billing.cancel') }}
</el-button>
<el-button
type="primary"
:disabled="!selectedRecord"
@click="handleConfirmSelect"
>
确认 (O)
{{ $t('billing.confirmSelect') }}
</el-button>
</div>
</template>
@@ -255,7 +255,8 @@
</template>
<script setup>
import {getCurrentInstance, reactive, ref, watch, nextTick, onMounted} from 'vue';
import {getCurrentInstance, reactive, ref, watch, nextTick, onMounted, computed} from 'vue';
import { useI18n } from 'vue-i18n';
import {getOutpatientRegistrationCurrent, reprintRegistration} from './outpatientregistration';
import {parseTime} from '@/utils/his';
import {formatDateStr} from '@/utils/index';
@@ -264,6 +265,7 @@ import outpatientRegistrationTemplate from '@/components/Print/OutpatientRegistr
import useUserStore from '@/store/modules/user';
const { proxy } = getCurrentInstance();
const { t } = useI18n();
const userStore = useUserStore();
const props = defineProps({
@@ -306,12 +308,12 @@ const form = reactive({
encounterId: '',
});
const rules = {
cardNo: [{ required: true, message: '就诊卡号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
organizationName: [{ required: true, message: '就诊科室不能为空', trigger: 'blur' }],
practitionerName: [{ required: true, message: '医生不能为空', trigger: 'blur' }],
};
const rules = computed(() => ({
cardNo: [{ required: true, message: t('billing.enterCardNo'), trigger: 'blur' }],
name: [{ required: true, message: t('billing.name'), trigger: 'blur' }],
organizationName: [{ required: true, message: t('registration.visitDepartment'), trigger: 'blur' }],
practitionerName: [{ required: true, message: t('billing.doctorName'), trigger: 'blur' }],
}));
// 监听open属性变化
watch(
@@ -337,7 +339,7 @@ watch(dialogVisible, (newVal) => {
// 搜索挂号记录并确认补打
async function handleSearch() {
if (!searchForm.cardNo) {
proxy.$modal.msgWarning('请输入就诊卡号');
proxy.$modal.msgWarning(t('billing.enterCardNo'));
return;
}
@@ -386,18 +388,18 @@ async function handleSearch() {
loading.value = false;
}
} else {
proxy.$modal.msgWarning('未查询到相关挂号记录,请检查就诊卡号是否正确');
proxy.$modal.msgWarning(t('billing.noRegRecord'));
resetForm();
loading.value = false;
}
} else {
proxy.$modal.msgWarning('查询失败: ' + (response.msg || '接口返回异常'));
proxy.$modal.msgWarning(t('billing.queryFailMsg', { msg: response.msg || t('billing.queryFail') }));
resetForm();
loading.value = false;
}
} catch (error) {
console.error('查询挂号记录异常:', error);
proxy.$modal.msgError('查询出错: ' + (error.message || '网络异常'));
proxy.$modal.msgError(t('billing.queryError', { error: error.message || t('billing.queryFail') }));
resetForm();
loading.value = false;
}
@@ -499,14 +501,14 @@ function fillForm(row) {
// 根据 statusEnum 判断状态
// 状态枚举可能需要根据实际情况调整
const statusMap = {
1: '已预约',
2: '已完成',
3: '已取消',
4: '进行中'
1: t('billing.statusReserved'),
2: t('billing.statusCompleted'),
3: t('billing.statusCancelled'),
4: t('billing.statusInProgress')
};
form.statusText = statusMap[row.statusEnum] || '已预约';
form.statusText = statusMap[row.statusEnum] || t('billing.statusReserved');
} else {
form.statusText = '已预约';
form.statusText = t('billing.statusReserved');
}
// 打印时间(当前时间)
@@ -549,7 +551,7 @@ function calculateSerialNo(row) {
// 提交补打挂号
async function handleSubmit() {
if (!form.encounterId) {
proxy.$modal.msgWarning('请先搜索并选择挂号记录');
proxy.$modal.msgWarning(t('billing.selectRegRecordFirst'));
loading.value = false;
return;
}
@@ -585,14 +587,14 @@ async function handleSubmit() {
const res = await reprintRegistration(submitData);
if (res.code === 200) {
proxy.$modal.msgSuccess('补打挂号成功');
proxy.$modal.msgSuccess(t('billing.reprintSuccess'));
// 不关闭补打对话框,直接显示打印预览
// 这样可以确保 form 数据不会丢失
loading.value = false;
showPrintPreview();
} else {
proxy.$modal.msgError(res.msg || '补打挂号失败');
proxy.$modal.msgError(res.msg || t('billing.reprintFail'));
loading.value = false;
}
} catch (error) {

View File

@@ -1,8 +1,8 @@
<template>
<template>
<div class="card-renewal-container">
<!-- 标题栏 -->
<div class="title-bar">
<h2>换卡处理</h2>
<h2>{{ $t('billing.cardRenewal') }}</h2>
</div>
<!-- 按钮栏 - 修改为水平排放 -->
@@ -15,7 +15,7 @@
style="min-width: 140px;"
@click="handlePatientSearch"
>
病人查询(Q)
{{ $t('billing.patientQuery') }}
</el-button>
<el-button
@@ -26,7 +26,7 @@
style="min-width: 140px;"
@click="handleConfirm"
>
确定 (O)
{{ $t('billing.confirmBtn') }}
</el-button>
<el-button
@@ -36,7 +36,7 @@
style="min-width: 140px;"
@click="handleClose"
>
关闭 (C)
{{ $t('billing.closeBtn') }}
</el-button>
</div>
@@ -45,10 +45,10 @@
<el-row :gutter="20">
<el-col :span="8">
<div class="input-item">
<label>病人姓名:</label>
<label>{{ $t('billing.patientNameLabel') }}</label>
<el-input
v-model="searchForm.patientName"
placeholder="请输入"
:placeholder="$t('common.pleaseEnter')"
clearable
@keyup.enter="handlePatientSearch"
/>
@@ -56,10 +56,10 @@
</el-col>
<el-col :span="8">
<div class="input-item">
<label>身份证号码:</label>
<label>{{ $t('billing.idCardLabel') }}</label>
<el-input
v-model="searchForm.idCard"
placeholder="请输入"
:placeholder="$t('common.pleaseEnter')"
clearable
@keyup.enter="handlePatientSearch"
/>
@@ -67,10 +67,10 @@
</el-col>
<el-col :span="8">
<div class="input-item">
<label>手机号码:</label>
<label>{{ $t('billing.phoneLabel') }}</label>
<el-input
v-model="searchForm.phoneNumber"
placeholder="请输入"
:placeholder="$t('common.pleaseEnter')"
clearable
@keyup.enter="handlePatientSearch"
/>
@@ -84,7 +84,7 @@
<el-row :gutter="20">
<el-col :span="8">
<div class="info-item">
<label>门诊号码</label>
<label>{{ $t('billing.outpatientNo') }}</label>
<div class="info-value">
{{ patientInfo?.outpatientNo || '' }}
</div>
@@ -92,7 +92,7 @@
</el-col>
<el-col :span="8">
<div class="info-item">
<label>病人姓名</label>
<label>{{ $t('billing.name') }}</label>
<div class="info-value">
{{ patientInfo?.patientName || '' }}
</div>
@@ -100,7 +100,7 @@
</el-col>
<el-col :span="8">
<div class="info-item">
<label>身份证号码</label>
<label>{{ $t('billing.idCardLabel').replace(':', '') }}</label>
<div class="info-value">
{{ patientInfo?.idCard || '' }}
</div>
@@ -114,7 +114,7 @@
>
<el-col :span="8">
<div class="info-item">
<label>手机号码</label>
<label>{{ $t('billing.phoneLabel').replace(':', '') }}</label>
<div class="info-value">
{{ patientInfo?.phoneNumber || '' }}
</div>
@@ -122,7 +122,7 @@
</el-col>
<el-col :span="8">
<div class="info-item">
<label>性别</label>
<label>{{ $t('billing.gender') }}</label>
<div class="info-value">
{{ patientInfo?.gender || '' }}
</div>
@@ -130,7 +130,7 @@
</el-col>
<el-col :span="8">
<div class="info-item">
<label>年龄</label>
<label>{{ $t('billing.age') }}</label>
<div class="info-value">
{{ patientInfo?.age || '' }}
</div>
@@ -142,10 +142,10 @@
<!-- 新门诊号码输入 -->
<div class="new-number-section">
<div class="input-item">
<label>新门诊号码:</label>
<label>{{ $t('billing.newOutpatientNo') }}</label>
<el-input
v-model="renewalForm.newOutpatientNo"
placeholder="请输入新门诊号码"
:placeholder="$t('billing.enterNewOutpatientNo')"
style="width: 250px;"
@keyup.enter="handleConfirm"
/>
@@ -168,7 +168,7 @@
<!-- 标题行 -->
<div style="display: flex; justify-content: flex-start; align-items: center; padding: 10px 20px;">
<h3 style="margin: 0; font-size: 16px; font-weight: 500; color: #303133;">
病人档案查询
{{ $t('billing.patientArchiveQuery') }}
</h3>
</div>
<!-- 按钮行 -->
@@ -178,13 +178,13 @@
style="background-color: #3B82F6; border-color: #3B82F6; padding: 8px 16px; font-size: 14px;"
@click="confirmSelectPatient"
>
确认(Q)
{{ $t('billing.confirmSelect') }}
</el-button>
<el-button
style="background-color: #EF4444; border-color: #EF4444; color: white; padding: 8px 16px; font-size: 14px;"
@click="showPatientList = false; selectedPatient = null"
>
关闭(C)
{{ $t('billing.closeSelect') }}
</el-button>
</div>
</div>
@@ -199,12 +199,12 @@
@cell-click="selectPatient"
>
<vxe-column
title="序号"
:title="$t('billing.seqNo')"
width="60"
type="seq"
/>
<vxe-column
title="病人姓名"
:title="$t('billing.name')"
width="120"
>
<template #default="scope">
@@ -212,7 +212,7 @@
</template>
</vxe-column>
<vxe-column
title="门诊号码"
:title="$t('billing.outpatientNo')"
width="120"
>
<template #default="scope">
@@ -220,7 +220,7 @@
</template>
</vxe-column>
<vxe-column
title="身份证号码"
:title="$t('billing.idCardLabel').replace(':', '')"
width="200"
>
<template #default="scope">
@@ -228,7 +228,7 @@
</template>
</vxe-column>
<vxe-column
title="手机号码"
:title="$t('billing.phoneLabel').replace(':', '')"
width="120"
>
<template #default="scope">
@@ -236,7 +236,7 @@
</template>
</vxe-column>
<vxe-column
title="性别"
:title="$t('billing.gender')"
width="80"
>
<template #default="scope">
@@ -244,7 +244,7 @@
</template>
</vxe-column>
<vxe-column
title="年龄"
:title="$t('billing.age')"
width="80"
>
<template #default="scope">
@@ -252,7 +252,7 @@
</template>
</vxe-column>
<vxe-column
title="出生年月"
:title="$t('billing.birthDate')"
width="120"
>
<template #default="scope">
@@ -283,7 +283,7 @@
<!-- 换卡成功提示 -->
<el-dialog
v-model="renewalSuccessVisible"
title="换卡成功"
:title="$t('billing.patientCardRenewalSuccess')"
width="400px"
:close-on-click-modal="false"
>
@@ -292,15 +292,15 @@
</div>
<p style="margin-top: 15px; font-size: 16px;">
患者换卡操作已成功完成!
{{ $t('billing.patientRenewalSuccessMsg') }}
</p>
<p style="margin-top: 10px;">
新门诊号码:{{ renewalForm.newOutpatientNo }}
{{ $t('billing.newOutpatientNo') }} {{ renewalForm.newOutpatientNo }}
</p>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="renewalSuccessVisible = false; resetForm">确定</el-button>
<el-button @click="renewalSuccessVisible = false; resetForm">{{ $t('billing.confirm') }}</el-button>
</span>
</template>
</el-dialog>
@@ -311,8 +311,10 @@
import {getCurrentInstance, onMounted, onUnmounted, reactive, ref} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {useRouter} from 'vue-router'
import {useI18n} from 'vue-i18n'
import {doCardRenewal, getPatientList} from './components/api.js';
const { t } = useI18n()
// 获取路由实例
const router = useRouter();
// 获取当前组件实例以访问全局属性
@@ -371,7 +373,7 @@ const handleCurrentChange = (newPage) => {
const handlePatientSearch = async () => {
// 检查是否至少填写了一个查询条件
if (!searchForm.patientName && !searchForm.idCard && !searchForm.phoneNumber) {
ElMessage.warning('请至少输入一个查询条件')
ElMessage.warning(t('billing.pleaseEnterQuery'))
return
}
@@ -407,7 +409,7 @@ const handleCurrentChange = (newPage) => {
// 设置为选中状态并自动确认,将患者信息展示到页面
selectedPatient.value = patient
confirmSelectPatient() // 自动调用确认选择方法,将患者信息展示到页面
ElMessage.success('已自动选中唯一患者')
ElMessage.success(t('billing.autoSelectUnique'))
} else {
// 如果有多条记录或不是第一页,显示患者列表供选择
// 确保每条患者记录都包含patientId字段优先使用id字段
@@ -420,10 +422,10 @@ const handleCurrentChange = (newPage) => {
} else {
// 无数据时重置总条数
total.value = 0
ElMessage.warning('未查询到患者信息')
ElMessage.warning(t('billing.noPatientFound'))
}
} else {
ElMessage.error('查询失败' + (response?.msg || '未知错误'))
ElMessage.error(t('billing.queryFail') + '' + (response?.msg || '未知错误'))
}
} catch (error) {
@@ -440,17 +442,17 @@ const handleCurrentChange = (newPage) => {
// 确定换卡
const handleConfirm = async () => {
if (!patientInfo.value) {
ElMessage.warning('请先查询患者信息')
ElMessage.warning(t('billing.pleaseQueryPatient'))
return
}
if (!renewalForm.newOutpatientNo) {
ElMessage.warning('请输入新门诊号码')
ElMessage.warning(t('billing.enterNewOutpatientNo'))
return
}
if (renewalForm.newOutpatientNo === patientInfo.value.outpatientNo) {
ElMessage.warning('新门诊号码不能与原号码相同')
ElMessage.warning(t('billing.newCardNoCannotSame'))
return
}
@@ -474,13 +476,13 @@ const handleConfirm = async () => {
if (patientInfo.value) {
patientInfo.value.outpatientNo = renewalForm.newOutpatientNo
}
ElMessage.success('换卡成功!')
ElMessage.success(t('billing.patientRenewalSuccess'))
} else {
ElMessage.error('换卡失败' + (res?.msg || '未知错误'))
ElMessage.error(t('billing.patientRenewalFail') + '' + (res?.msg || '未知错误'))
}
} catch (error) {
ElMessage.error('换卡失败,卡号已存在')
ElMessage.error(t('billing.patientRenewalFailCardExists'))
// 可以在这里添加错误监控或日志记录
} finally {
loading.value = false
@@ -490,7 +492,7 @@ const handleConfirm = async () => {
// 关闭窗口,同时关闭标签页并返回上一级页面
const handleClose = () => {
// 显示确认对话框
ElMessageBox.confirm('确定要关闭此页面吗?', '提示', {
ElMessageBox.confirm(t('billing.closeConfirm'), t('common.tip'), {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
@@ -505,7 +507,7 @@ const handleClose = () => {
}).catch(() => {
// 用户取消操作,不执行任何操作
// 可以选择显示一个提示消息
ElMessage.info('已取消关闭操作')
ElMessage.info(t('billing.cancelClose'))
})
}
@@ -564,13 +566,13 @@ onUnmounted(() => {
// 选择患者(仅设置选中状态)
const selectPatient = (row) => {
selectedPatient.value = row
ElMessage.warning('已选择患者,请点击确定')
ElMessage.warning(t('billing.selectPatientWarning'))
}
// 确认选择患者
const confirmSelectPatient = () => {
if (!selectedPatient.value) {
ElMessage.warning('请先选择患者')
ElMessage.warning(t('billing.selectPatient'))
return
}
@@ -591,7 +593,7 @@ const confirmSelectPatient = () => {
}
showPatientList.value = false
ElMessage.success('已选择患者:' + (row.patientName || row.name))
ElMessage.success(t('billing.opSuccess'))
// 重置选中状态
selectedPatient.value = null
}

View File

@@ -1,8 +1,8 @@
<template>
<template>
<div class="patient-search-container">
<!-- 标题栏 -->
<div class="title-bar">
<h2>病人档案查询</h2>
<h2>{{ $t('billing.patientArchiveQuery') }}</h2>
<div class="button-bar">
<el-button
type="primary"
@@ -11,7 +11,7 @@
icon="el-icon-check"
@click="handleQuery"
>
确认(Q)
{{ $t('billing.confirmSelect') }}
</el-button>
<el-button
type="danger"
@@ -19,7 +19,7 @@
icon="el-icon-close"
@click="handleClose"
>
关闭(C)
{{ $t('billing.closeSelect') }}
</el-button>
</div>
</div>
@@ -29,10 +29,10 @@
<el-row :gutter="20">
<el-col :span="8">
<div class="form-item">
<label>病人姓名:</label>
<label>{{ $t('billing.patientNameLabel') }}</label>
<el-input
v-model="searchForm.patientName"
placeholder="请输入病人姓名"
:placeholder="$t('billing.searchPlaceholderName')"
clearable
@keyup.enter="handleQuery"
/>
@@ -40,10 +40,10 @@
</el-col>
<el-col :span="8">
<div class="form-item">
<label>身份证号码:</label>
<label>{{ $t('billing.idCardLabel') }}</label>
<el-input
v-model="searchForm.idCard"
placeholder="请输入身份证号码"
:placeholder="$t('billing.idCard')"
clearable
@keyup.enter="handleQuery"
/>
@@ -51,10 +51,10 @@
</el-col>
<el-col :span="8">
<div class="form-item">
<label>手机号码:</label>
<label>{{ $t('billing.phoneLabel') }}</label>
<el-input
v-model="searchForm.phoneNumber"
placeholder="请输入手机号码"
:placeholder="$t('billing.phoneLabel').replace(':', '')"
clearable
@keyup.enter="handleQuery"
/>
@@ -74,13 +74,13 @@
@cell-click="handleRowClick"
>
<vxe-column
title="序号"
:title="$t('billing.seqNo')"
type="seq"
width="80"
align="center"
/>
<vxe-column
title="病人姓名"
:title="$t('billing.name')"
width="120"
align="center"
>
@@ -89,7 +89,7 @@
</template>
</vxe-column>
<vxe-column
title="门诊号码"
:title="$t('billing.outpatientNo')"
width="150"
align="center"
>
@@ -98,7 +98,7 @@
</template>
</vxe-column>
<vxe-column
title="身份证号码"
:title="$t('billing.idCardLabel').replace(':', '')"
width="200"
align="center"
>
@@ -107,7 +107,7 @@
</template>
</vxe-column>
<vxe-column
title="手机号码"
:title="$t('billing.phoneLabel').replace(':', '')"
width="120"
align="center"
>
@@ -116,7 +116,7 @@
</template>
</vxe-column>
<vxe-column
title="性别"
:title="$t('billing.gender')"
width="80"
align="center"
>
@@ -125,7 +125,7 @@
</template>
</vxe-column>
<vxe-column
title="年龄"
:title="$t('billing.age')"
width="80"
align="center"
>
@@ -134,7 +134,7 @@
</template>
</vxe-column>
<vxe-column
title="出生年月"
:title="$t('billing.birthDate')"
width="120"
align="center"
>
@@ -150,8 +150,11 @@
<script setup>
import {computed, onMounted, onUnmounted, reactive, ref, watch} from 'vue'
import {ElMessage} from 'element-plus'
import {useI18n} from 'vue-i18n'
import {getOutpatientRegistrationList} from '../outpatientregistration/components/outpatientregistration'
const { t } = useI18n()
// 搜索表单
const searchForm = reactive({
patientName: '',
@@ -197,7 +200,7 @@ watch(searchKey, (newValue) => {
// 处理行点击
const handleRowClick = (row) => {
selectedPatient.value = row
ElMessage.success(`已选择患者:${row.patientName}`)
ElMessage.success(t('billing.opSuccess'))
}
// 查询患者信息和确认选择
@@ -206,13 +209,13 @@ const handleQuery = async () => {
if (selectedPatient.value) {
// 发射选择患者事件
emit('selectPatient', selectedPatient.value)
ElMessage.success(`已确认选择患者:${selectedPatient.value.patientName}`)
ElMessage.success(t('billing.opSuccess'))
return
}
// 检查是否至少填写了一个查询条件
if (!searchKey.value) {
ElMessage.warning('请至少输入一个查询条件')
ElMessage.warning(t('billing.pleaseEnterQuery'))
return
}
@@ -235,14 +238,14 @@ const handleQuery = async () => {
}))
if (patientList.value.length === 0) {
ElMessage.warning('未找到符合条件的患者信息')
ElMessage.warning(t('billing.noPatientFound'))
}
} else {
ElMessage.error('查询失败')
ElMessage.error(t('billing.queryFail'))
patientList.value = []
}
} catch (error) {
ElMessage.error('查询失败,请稍后重试')
ElMessage.error(t('billing.queryFailRetry'))
console.error('查询失败:', error)
patientList.value = []
} finally {

View File

@@ -2,16 +2,16 @@
<div class="app-container">
<el-card shadow="never">
<template #header>
<span class="card-title">挂号收费记录</span>
<span class="card-title">{{ $t('billing.registerChargeRecordTitle') }}</span>
</template>
<el-form
:inline="true"
:model="queryParams"
>
<el-form-item label="搜索">
<el-form-item :label="$t('billing.search')">
<el-input
v-model="queryParams.searchKey"
placeholder="搜索"
:placeholder="$t('billing.search')"
clearable
@keyup.enter="handleQuery"
/>
@@ -22,7 +22,7 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('billing.search') }}
</el-button>
</el-form-item>
</el-form>
@@ -33,29 +33,29 @@
>
<vxe-column
type="seq"
title="序号"
:title="$t('billing.seqNo')"
width="60"
/>
<vxe-column
field="name"
title="名称"
:title="$t('billing.nameCol')"
/>
<vxe-column
field="date"
title="日期"
:title="$t('billing.dateCol')"
/>
<vxe-column
field="status"
title="状态"
:title="$t('billing.statusCol')"
>
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'info'">
{{ row.status === '0' ? '正常' : '停用' }}
{{ row.status === '0' ? $t('billing.normal') : $t('billing.disabled') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
title="操作"
:title="$t('billing.operation')"
width="120"
>
<template #default="{ row }">
@@ -64,7 +64,7 @@
link
@click="handleDetail(row)"
>
详情
{{ $t('billing.detail') }}
</el-button>
</template>
</vxe-column>
@@ -75,10 +75,13 @@
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const queryParams = ref({ searchKey: '', pageNum: 1, pageSize: 10 })
const tableData = ref([])
const handleQuery = async () => { tableData.value = [] }
const handleDetail = (row) => { ElMessage.info('详情') }
const handleDetail = (row) => { ElMessage.info(t('billing.detail')) }
onMounted(() => handleQuery())
</script>
<style scoped>.card-title { font-weight: bold; font-size: 16px; }</style>

View File

@@ -2,16 +2,16 @@
<div class="app-container">
<el-card shadow="never">
<template #header>
<span class="card-title">排班管理</span>
<span class="card-title">{{ $t('billing.schedule') }}</span>
</template>
<el-form
:inline="true"
:model="queryParams"
>
<el-form-item label="搜索">
<el-form-item :label="$t('billing.search')">
<el-input
v-model="queryParams.searchKey"
placeholder="搜索"
:placeholder="$t('billing.search')"
clearable
@keyup.enter="handleQuery"
/>
@@ -22,7 +22,7 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('billing.search') }}
</el-button>
</el-form-item>
</el-form>
@@ -33,29 +33,29 @@
>
<vxe-column
type="seq"
title="序号"
:title="$t('billing.seqNo')"
width="60"
/>
<vxe-column
field="name"
title="名称"
:title="$t('billing.nameCol')"
/>
<vxe-column
field="date"
title="日期"
:title="$t('billing.dateCol')"
/>
<vxe-column
field="status"
title="状态"
:title="$t('billing.statusCol')"
>
<template #default="{ row }">
<el-tag :type="row.status === '0' ? 'success' : 'info'">
{{ row.status === '0' ? '正常' : '停用' }}
{{ row.status === '0' ? $t('billing.normal') : $t('billing.disabled') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
title="操作"
:title="$t('billing.operation')"
width="120"
>
<template #default="{ row }">
@@ -64,7 +64,7 @@
link
@click="handleDetail(row)"
>
详情
{{ $t('billing.detail') }}
</el-button>
</template>
</vxe-column>
@@ -75,10 +75,13 @@
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const queryParams = ref({ searchKey: '', pageNum: 1, pageSize: 10 })
const tableData = ref([])
const handleQuery = async () => { tableData.value = [] }
const handleDetail = (row) => { ElMessage.info('详情') }
const handleDetail = (row) => { ElMessage.info(t('billing.detail')) }
onMounted(() => handleQuery())
</script>
<style scoped>.card-title { font-weight: bold; font-size: 16px; }</style>

View File

@@ -8,34 +8,34 @@
<!-- 左侧患者基本信息区 -->
<el-card style="width: 30%">
<template #header>
<span style="vertical-align: middle">患者基本信息</span>
<span style="vertical-align: middle">{{ $t('billing.patientBasicInfo') }}</span>
</template>
<el-descriptions
:column="1"
border
>
<el-descriptions-item label="病历号">
<el-descriptions-item :label="$t('billing.medicalRecordNo')">
{{ patientInfo.encounterBusNo }}
</el-descriptions-item>
<el-descriptions-item label="姓名">
<el-descriptions-item :label="$t('billing.name')">
{{ patientInfo.patientName }}
</el-descriptions-item>
<el-descriptions-item label="性别">
<el-descriptions-item :label="$t('billing.gender')">
{{ patientInfo.genderEnum_enumText }}
</el-descriptions-item>
<el-descriptions-item label="年龄">
<el-descriptions-item :label="$t('billing.age')">
{{ patientInfo.age }}
</el-descriptions-item>
<el-descriptions-item label="科室">
<el-descriptions-item :label="$t('billing.department')">
{{ patientInfo.organizationName }}
</el-descriptions-item>
<el-descriptions-item label="就诊时间">
<el-descriptions-item :label="$t('billing.visitTime')">
{{ formatDateStr(patientInfo.receptionTime, 'YYYY-MM-DD HH:mm:ss') }}
</el-descriptions-item>
<el-descriptions-item label="手术单号">
<el-descriptions-item :label="$t('billing.surgeryNo')">
{{ surgeryInfo.surgeryNo }}
</el-descriptions-item>
<el-descriptions-item label="手术名称">
<el-descriptions-item :label="$t('billing.surgeryName')">
{{ surgeryInfo.surgeryName }}
</el-descriptions-item>
</el-descriptions>
@@ -45,7 +45,7 @@
<div style="width: 69%">
<el-card style="min-width: 1100px">
<template #header>
<span style="vertical-align: middle">收费项目</span>
<span style="vertical-align: middle">{{ $t('billing.chargeItems') }}</span>
</template>
<div style="margin-bottom: 10px">
<el-button
@@ -53,7 +53,7 @@
:disabled="buttonDisabled"
@click="confirmCharge()"
>
确认收费
{{ $t('billing.confirmCharge') }}
</el-button>
<el-button
type="primary"
@@ -61,7 +61,7 @@
style="width: 65px"
@click="handleReadCard('01')"
>
电子凭证
{{ $t('billing.electronicCertificate') }}
</el-button>
<el-button
type="primary"
@@ -69,10 +69,10 @@
style="width: 65px"
@click="handleReadCard('03')"
>
医保卡
{{ $t('billing.medicalInsuranceCard') }}
</el-button>
<span style="float: right">
合计金额{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}
{{ $t('billing.totalAmount') }}{{ totalAmounts ? totalAmounts.toFixed(2) : 0 }}{{ $t('billing.yuan') }}
</span>
</div>
<vxe-table
@@ -91,40 +91,40 @@
width="55"
/>
<vxe-column
title="单据号"
:title="$t('billing.docNo')"
align="center"
field="busNo"
width="180"
/>
<vxe-column
title="收费项目"
:title="$t('billing.chargeItems')"
align="center"
field="itemName"
width="200"
/>
<vxe-column
title="数量"
:title="$t('billing.quantity')"
align="center"
field="quantityValue"
width="80"
/>
<vxe-column
title="医疗类型"
:title="$t('billing.medicalType')"
align="center"
field="medTypeCode_dictText"
/>
<vxe-column
title="医保编码"
:title="$t('billing.insuranceCode')"
align="center"
field="ybNo"
/>
<vxe-column
title="费用性质"
:title="$t('billing.feeNature')"
align="center"
field="contractName"
/>
<vxe-column
title="收费状态"
:title="$t('billing.chargeStatus')"
align="center"
field="statusEnum_enumText"
width="150"
@@ -160,22 +160,22 @@
</template>
</vxe-column>
<vxe-column
title="金额"
:title="$t('billing.amount')"
align="right"
field="totalPrice"
header-align="center"
>
<template #default="scope">
{{ scope.row.totalPrice.toFixed(2) + ' 元' || '0.00' + ' 元' }}
{{ scope.row.totalPrice.toFixed(2) + ' ' + $t('billing.yuan') || '0.00' + ' ' + $t('billing.yuan') }}
</template>
</vxe-column>
<vxe-column
title="收款人"
:title="$t('billing.cashier')"
align="center"
field="entererId_dictText"
/>
<vxe-column
title="操作"
:title="$t('billing.operation')"
align="center"
fixed="right"
header-align="center"
@@ -188,7 +188,7 @@
type="primary"
@click="printCharge(scope.row)"
>
打印
{{ $t('billing.print') }}
</el-button>
</template>
</vxe-column>
@@ -219,11 +219,14 @@
</template>
<script setup name="SurgeryCharge">
import { useI18n } from 'vue-i18n';
import {
getChargeList,
precharge,
getChargeInfo,
} from '../cliniccharge/components/api';
const { t } = useI18n();
import {invokeYbPlugin5000, invokeYbPlugin5001} from '@/api/public';
import ChargeDialog from '../cliniccharge/components/chargeDialog.vue';
import {formatDateStr} from '@/utils';
@@ -363,7 +366,7 @@ function handleClose(value, msg) {
function confirmCharge() {
let selectRows = chargeListRef.value.getSelectionRows();
if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目');
proxy.$modal.msgWarning(t('billing.selectChargeItem'));
return;
}
chargeItemIdList.value = selectRows.map((item) => {
@@ -395,7 +398,7 @@ function confirmCharge() {
}) || [];
openDialog.value = true;
} else {
proxy.$modal.msgError(res?.msg || '预结算失败');
proxy.$modal.msgError(res?.msg || t('billing.preSettleFail'));
}
});
}
@@ -420,7 +423,7 @@ async function handleReadCard(value) {
})
.then((res) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
loadingText.value = t('billing.reading');
jsonResult = res.data;
})
.catch(() => {
@@ -445,7 +448,7 @@ async function handleReadCard(value) {
break;
case '03': // 医保卡
readCardLoading.value = true;
loadingText.value = '正在读取...';
loadingText.value = t('billing.reading');
await invokeYbPlugin5001(
JSON.stringify({
FunctionId: 1,
@@ -479,7 +482,7 @@ async function handleReadCard(value) {
if (userMessage.certNo) {
let selectRows = chargeListRef.value.getSelectionRows();
if (selectRows.length == 0) {
proxy.$modal.msgWarning('请选择一条收费项目');
proxy.$modal.msgWarning(t('billing.selectChargeItem'));
return;
}
chargeItemIdList.value = selectRows.map((item) => {
@@ -514,7 +517,7 @@ async function handleReadCard(value) {
});
openDialog.value = true;
} else {
proxy.$modal.msgError(res?.msg || '预结算失败');
proxy.$modal.msgError(res?.msg || t('billing.preSettleFail'));
}
});
}

View File

@@ -1,4 +1,4 @@
<template>
<template>
<div class="app-continer">
<el-form
ref="queryRef"
@@ -6,12 +6,12 @@
:inline="true"
>
<el-form-item
label="患者姓名"
:label="$t('billing.patientName')"
prop="patientName"
>
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者姓名"
:placeholder="$t('billing.searchPlaceholderPatient')"
/>
</el-form-item>
<el-form-item>
@@ -20,13 +20,13 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('billing.search') }}
</el-button>
<el-button
icon="Refresh"
@click="resetQuery"
>
重置
{{ $t('billing.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -38,19 +38,19 @@
border
>
<vxe-column
title="患者姓名"
:title="$t('billing.patientName')"
align="center"
field="patientName"
show-overflow="title"
/>
<vxe-column
title="支付单号"
:title="$t('billing.payBusNo')"
align="center"
field="paymentBusNo"
show-overflow="title"
/>
<vxe-column
title="交易金额(元)"
:title="$t('billing.txnAmount')"
align="right"
field="txnAmt"
header-align="center"
@@ -58,19 +58,19 @@
show-overflow="title"
/>
<vxe-column
title="交易类型"
:title="$t('billing.txnType')"
align="center"
field="tranType"
show-overflow="title"
/>
<vxe-column
title="支付方式"
:title="$t('billing.payTypeCol')"
align="center"
field="payType"
show-overflow="title"
/>
<vxe-column
title="交易时间"
:title="$t('billing.txnTime')"
align="center"
field="txnTime"
show-overflow="title"
@@ -80,43 +80,43 @@
</template>
</vxe-column>
<vxe-column
title="原交易类型"
:title="$t('billing.origTxnType')"
align="center"
field="orgTranType"
show-overflow="title"
/>
<vxe-column
title="原交易类型"
:title="$t('billing.origTxnType')"
align="center"
field="orgTranType"
show-overflow="title"
/>
<vxe-column
title="第三方优惠说明"
:title="$t('billing.thirdPartyDiscount')"
align="center"
field="otherMsg"
show-overflow="title"
/>
<vxe-column
title="错误信息"
:title="$t('billing.errorMsg')"
align="center"
field="errMsg"
show-overflow="title"
/>
<vxe-column
title="查询结果"
:title="$t('billing.queryResult')"
align="center"
field="queryResult"
show-overflow="title"
/>
<vxe-column
title="查询结果说明"
:title="$t('billing.queryResultMsg')"
align="center"
field="queryResultMsg"
show-overflow="title"
/>
<vxe-column
title="操作"
:title="$t('billing.operation')"
align="center"
field="paymentEnum_enumText"
width="340"
@@ -128,7 +128,7 @@
:disabled="!scope.row.paymentId"
@click="getPayInfo(scope.row.paymentId)"
>
支付结果查询
{{ $t('billing.payResultQuery') }}
</el-button>
<el-button
type="warning"
@@ -136,7 +136,7 @@
:disabled="!scope.row.paymentId"
@click="returnFee(scope.row.paymentId)"
>
退费
{{ $t('billing.refundItem') }}
</el-button>
<el-button
type="danger"
@@ -145,14 +145,14 @@
:disabled="!scope.row.paymentId"
@click="returnFeeNext(scope.row.paymentId)"
>
隔天退费
{{ $t('billing.nextDayRefund') }}
</el-button>
<el-button
type="success"
link
@click="returnFeeResultQuery(scope.row.id)"
>
退费结果查询
{{ $t('billing.refundResultQuery') }}
</el-button>
</template>
</vxe-column>
@@ -169,8 +169,11 @@
<script setup name="ClinicRecord">
const { proxy } = getCurrentInstance();
import { useI18n } from 'vue-i18n';
import {getList, getPayinfo, returnfee, returnFeednext, returnResult} from './components/api.js';
const { t } = useI18n();
const total = ref(0);
const queryParams = ref({
pageNo: 1,
@@ -182,19 +185,19 @@ const loading = ref(false);
const getPayInfo = (paymentId) => {
console
getPayinfo({ paymentId }).then((res) => {
proxy.$message.success('支付结果查询成功');
proxy.$message.success(t('billing.opSuccess'));
console.log(res);
});
};
const returnFee = (paymentId) => {
returnfee({ paymentId }).then((res) => {
proxy.$message.success('退费成功');
proxy.$message.success(t('billing.opSuccess'));
console.log(res);
});
};
const returnFeeNext = (paymentId) => {
returnFeednext({ paymentId }).then((res) => {
proxy.$message.success('隔天退费成功');
proxy.$message.success(t('billing.opSuccess'));
console.log(res);
});
};

View File

@@ -10,25 +10,25 @@
label-position="right"
>
<el-form-item
label="患者信息"
:label="$t('pharmacy.patientInfo')"
prop="searchKey"
>
<el-input
v-model="queryParams.searchKey"
placeholder="请输入姓名/证件号"
:placeholder="$t('pharmacy.placeholderNameOrId')"
clearable
style="width: 160px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item
label="发药状态"
:label="$t('pharmacy.dispenseStatus')"
prop="departmentId"
style="margin-left: 10px"
>
<el-select
v-model="queryParams.statusEnum"
placeholder="请选择发药状态"
:placeholder="$t('pharmacy.placeholderSelectDispenseStatus')"
clearable
style="width: 160px"
@change="handleQuery"
@@ -41,12 +41,12 @@
/>
</el-select>
</el-form-item>
<el-form-item label="就诊日期">
<el-form-item :label="$t('pharmacy.visitDate')">
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:start-placeholder="$t('pharmacy.startDate')"
:end-placeholder="$t('pharmacy.endDate')"
style="width: 250px"
value-format="YYYY-MM-DD"
@change="handleQuery"
@@ -73,10 +73,10 @@
type="primary"
@click="handleQuery"
>
搜索
{{ $t('common.search') }}
</el-button>
<el-button @click="resetQuery">
重置
{{ $t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -91,31 +91,31 @@
>
<vxe-column
field="patientName"
title="姓名"
:title="$t('pharmacy.name')"
width="130"
align="center"
/>
<vxe-column
field="genderEnum_enumText"
title="性别"
:title="$t('pharmacy.gender')"
width="80"
align="center"
/>
<vxe-column
field="age"
title="年龄"
:title="$t('pharmacy.age')"
width="80"
align="center"
/>
<vxe-column
field="phone"
title="电话"
:title="$t('pharmacy.phone')"
width="80"
align="center"
/>
<vxe-column
field="receptionTime"
title="就诊日期"
:title="$t('pharmacy.visitDateCol')"
align="center"
>
<template #default="scope">
@@ -182,11 +182,11 @@
<span
style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px"
>
调配药师
{{ $t('pharmacy.preparer') }}
</span>
<el-select
v-model="preparerDoctor"
placeholder="调配药师"
:placeholder="$t('pharmacy.placeholderPreparer')"
style="width: 160px"
>
<el-option
@@ -199,11 +199,11 @@
<span
style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px"
>
药品分类
{{ $t('pharmacy.drugCategory') }}
</span>
<el-select
v-model="tcmFlag"
placeholder="药品分类"
:placeholder="$t('pharmacy.placeholderDrugCategory')"
style="width: 160px"
@change="
() => {
@@ -223,11 +223,11 @@
<span
style="color: #606266; font-size: 14px; font-weight: 700; margin-right: 15px"
>
项目
{{ $t('pharmacy.project') }}
</span>
<el-select
v-model="projectTypeCode"
placeholder="项目"
:placeholder="$t('pharmacy.placeholderProject')"
style="width: 160px"
:clearable="false"
@change="
@@ -240,15 +240,15 @@
"
>
<el-option
label="全部"
:label="$t('pharmacy.all')"
value="1"
/>
<el-option
label="药品"
:label="$t('pharmacy.drug')"
value="2"
/>
<el-option
label="耗材"
:label="$t('pharmacy.consumable')"
value="3"
/>
</el-select>
@@ -258,24 +258,24 @@
style="margin-left: 30px"
@click="handleBatch()"
>
批量发药
{{ $t('pharmacy.batchDispense') }}
</el-button>
<el-button
type="primary"
style="margin-left: 30px"
@click="handleScan()"
>
扫码
{{ $t('pharmacy.scan') }}
</el-button>
<el-button
type="primary"
style="margin-left: 30px"
@click="printPrescription()"
>
处方打印
{{ $t('pharmacy.prescriptionPrint') }}
</el-button>
<div style="position: absolute; top: 30px; right: 25px">
总金额{{ medicineTotalPrice ? medicineTotalPrice.toFixed(2) : "0.00" }}
{{ $t('pharmacy.totalAmount') }}{{ medicineTotalPrice ? medicineTotalPrice.toFixed(2) : "0.00" }}{{ $t('pharmacy.yuan') }}
</div>
</div>
<vxe-table
@@ -297,37 +297,37 @@
/>
<vxe-column
field="prescriptionNo"
title="处方号"
:title="$t('pharmacy.prescriptionNo')"
width="120"
align="center"
/>
<vxe-column
field="conditionName"
title="诊断"
:title="$t('pharmacy.diagnosis')"
width="120"
align="center"
/>
<vxe-column
field="dispenseEnum_enumText"
title="处方类型"
:title="$t('pharmacy.prescriptionType')"
width="120"
align="center"
/>
<vxe-column
field="itemName"
title="项目名称"
:title="$t('pharmacy.itemName')"
width="160"
align="center"
/>
<vxe-column
field="merchandiseName"
title="商品名称"
:title="$t('pharmacy.merchandiseName')"
width="160"
align="center"
/>
<vxe-column
field="quantity"
title="发药数量"
:title="$t('pharmacy.dispenseQty')"
width="130"
align="center"
>
@@ -367,7 +367,7 @@
</vxe-column>
<vxe-column
field="lotNumber"
title="批次号"
:title="$t('pharmacy.lotNumber')"
width="160"
align="center"
>
@@ -405,7 +405,7 @@
</vxe-column>
<vxe-column
field="statusEnum_enumText"
title="发药状态"
:title="$t('pharmacy.dispenseStatusCol')"
width="100"
align="center"
>
@@ -417,7 +417,7 @@
</vxe-column>
<vxe-column
field="dispensePerDuration"
title="天数"
:title="$t('pharmacy.days')"
width="80"
align="center"
/>
@@ -425,7 +425,7 @@
<!-- <vxe-column field="quantity" title="发药数量" width="100" align="center" /> -->
<vxe-column
field="totalVolume"
title="规格"
:title="$t('pharmacy.spec')"
width="100"
align="center"
/>
@@ -444,7 +444,7 @@
<vxe-column
v-if="tcmFlag == '0'"
field="traceNo"
title="追溯码"
:title="$t('pharmacy.traceNo')"
width="180"
align="center"
>
@@ -457,7 +457,7 @@
<el-input
:ref="'traceNoRef' + scope.rowIndex"
v-model="scope.row.traceNo"
placeholder="请输入追溯码"
:placeholder="$t('pharmacy.placeholderTraceNo')"
@input="handleTraceNoInput(scope.row, scope.rowIndex)"
/>
</el-tooltip>
@@ -465,7 +465,7 @@
</vxe-column>
<vxe-column
field="totalPrice"
title="金额"
:title="$t('pharmacy.amount')"
width="100"
:formatter="formatPrice"
align="right"
@@ -473,37 +473,37 @@
/>
<vxe-column
field="locationName"
title="发药药房"
:title="$t('pharmacy.dispensePharmacy')"
width="90"
align="center"
/>
<vxe-column
field="manufacturerText"
title="生产厂家"
:title="$t('pharmacy.manufacturer')"
width="200"
align="center"
/>
<vxe-column
field="doctorName"
title="开单医生"
:title="$t('pharmacy.orderingDoctor')"
width="100"
align="center"
/>
<!-- <vxe-column field="dose" title="剂量" width="100" align="center" /> -->
<vxe-column
field="rateCode"
title="频次"
:title="$t('pharmacy.frequency')"
width="100"
align="center"
/>
<vxe-column
field="methodCode_dictText"
title="用法"
:title="$t('pharmacy.usage')"
width="100"
align="center"
/>
<vxe-column
title="操作"
:title="$t('pharmacy.operation')"
align="center"
width="160"
fixed="right"
@@ -517,7 +517,7 @@
icon="SuccessFilled"
@click="handleBatch(scope.row)"
>
发药
{{ $t('pharmacy.dispense') }}
</el-button>
<el-button
link
@@ -526,7 +526,7 @@
icon="CircleClose"
@click="backMedicine(scope.row)"
>
作废
{{ $t('pharmacy.void') }}
</el-button>
</template>
</vxe-column>
@@ -552,13 +552,13 @@
</div>
<el-dialog
v-model="showDialog"
title="选择作废原因"
:title="$t('pharmacy.selectVoidReason')"
width="30%"
>
<!-- 下拉选择框 -->
<el-select
v-model="notPerformedReasonEnum"
placeholder="请选择作废原因"
:placeholder="$t('pharmacy.placeholderSelectVoidReason')"
>
<el-option
v-for="item in backReason"
@@ -574,8 +574,8 @@
<el-button
type="primary"
@click="handleConfirm"
> </el-button>
<el-button @click="handleCancel"> </el-button>
>{{ $t('pharmacy.confirm') }}</el-button>
<el-button @click="handleCancel">{{ $t('pharmacy.cancel') }}</el-button>
</span>
</template>
</el-dialog>
@@ -589,7 +589,8 @@
</template>
<script setup name="westernmedicine">
import {onMounted, ref} from 'vue';
import {onMounted, ref, computed} from 'vue';
import {useI18n} from 'vue-i18n';
import {ElMessage} from 'element-plus';
import {
deviceDispense,
@@ -616,6 +617,7 @@ import useUserStore from '@/store/modules/user';
const userStore = useUserStore();
const { t } = useI18n();
const {proxy} = getCurrentInstance();
const showSearch = ref(true);
const total = ref(0);
@@ -655,13 +657,13 @@ const ypName = ref('');
const medicineTotalPrice = ref(0);
const projectTypeCode = ref("2");
const selectedRow = ref(null);
const medCategoryCode = ref([
const medCategoryCode = computed(() => [
{
label: "西药中成药",
label: t('pharmacy.westernChinese'),
value: "0",
},
{
label: "中药",
label: t('pharmacy.chinese'),
value: "1",
},
]);
@@ -697,7 +699,7 @@ function submit(value) {
itemTraceNo(list).then((res) => {
if (res.code === 200) {
if (!res.data) {
proxy.$modal.msgWarning("未在库存中匹配到追溯码,请在发药列表中单独扫描");
proxy.$modal.msgWarning(t('pharmacy.msgNoMatchTraceNo'));
openTraceNoDialog.value = false;
proxy.$refs["traceNoRef0"].focus();
return;
@@ -707,7 +709,7 @@ function submit(value) {
res.data[item.medicineId] &&
res.data[item.medicineId].split(",") > item.quantity
) {
proxy.$modal.msgWarning("操作失败");
proxy.$modal.msgWarning(t('pharmacy.msgOperationFailed'));
return;
}
medicineInfoList.value[index].traceNo = res.data[item.medicineId];
@@ -760,13 +762,13 @@ function getList() {
async function printPrescription() {
// 空值检查 - 防止 tableRef 为空时报错
if (!tableRef.value) {
proxy.$modal.msgWarning("表格组件未初始化,请刷新页面重试");
proxy.$modal.msgWarning(t('pharmacy.printWarningNoTable'));
return;
}
const selectedRows = tableRef.value.getSelectionRows();
if (!selectedRows || selectedRows.length === 0) {
proxy.$modal.msgWarning("未选择要打印的项目,请重新选择,打印失败");
proxy.$modal.msgWarning(t('pharmacy.printWarningNoSelect'));
return;
}
@@ -777,7 +779,7 @@ async function printPrescription() {
const res = await advicePrint({requestIds: requestIds, isPrescription: "1"});
if (!res || !res.data || !res.data.adviceItemList) {
proxy.$modal.msgWarning("获取打印数据失败,请稍后重试");
proxy.$modal.msgWarning(t('pharmacy.printWarningNoData'));
return;
}
@@ -883,7 +885,7 @@ async function printPrescription() {
});
} catch (error) {
console.error('处方打印失败:', error);
proxy.$modal.msgError('处方打印失败: ' + (error.message || '未知错误'));
proxy.$modal.msgError(t('pharmacy.printFailed') + ': ' + (error.message || t('common.error')));
}
}
@@ -918,14 +920,14 @@ function formatLotNumberLabel(row, item) {
if (row.unitCode == item.maxUnitCode) {
return (
item.inventoryLotNumber +
' 剩余' +
' ' + t('pharmacy.remaining') + '' +
formatInventory(
item.inventoryQuantity,
item.partPercent,
item.maxUnitCode_dictText,
item.inventoryUnitCode_dictText
) +
' 有效期至' +
' ' + t('pharmacy.expDate') + '' +
proxy.formatDateStr(item.expirationDate, 'YYYY-MM-DD')
);
} else {
@@ -935,7 +937,7 @@ function formatLotNumberLabel(row, item) {
item.inventoryQuantity +
' ' +
item.inventoryUnitCode_dictText +
' 有效期至' +
' ' + t('pharmacy.expDate') + '' +
proxy.formatDateStr(item.expirationDate, 'YYYY-MM-DD')
);
}
@@ -1052,9 +1054,9 @@ function handleCellDbClick(row, column, cellValue, event) {
function formatPrice(row, column, cellValue) {
if (cellValue === null || cellValue === undefined) {
return "0.00 "; // 如果值为空返回0.00
return "0.00 " + t('pharmacy.yuan');
}
return cellValue.toFixed(2) + " "; // 保留两位小数
return cellValue.toFixed(2) + " " + t('pharmacy.yuan');
}
function tagType(statusEnum) {
@@ -1130,7 +1132,7 @@ function getMedicineList(encounterId) {
loading.value = false;
})
.catch((error) => {
proxy.$modal.msgError('获取数据失败');
proxy.$modal.msgError(t('pharmacy.msgDispenseFailed'));
});
} else if (projectTypeCode.value == 2) {
// 只调用listWesternmedicine接口
@@ -1228,7 +1230,7 @@ function submitMedicine(saveList) {
promises.push(
deviceDispense(deviceList).then((res) => {
if (res.code != 200) {
throw new Error("耗材发药失败");
throw new Error(t('pharmacy.msgDispenseFailed'));
}
return res;
})
@@ -1247,7 +1249,7 @@ function submitMedicine(saveList) {
promises.push(
prepareMedicion(preparationList).then((res) => {
if (res.code != 200) {
throw new Error('药品发药失败');
throw new Error(t('pharmacy.msgDispenseFailed'));
}
return res;
})
@@ -1257,7 +1259,7 @@ function submitMedicine(saveList) {
promises.push(
updateMedicion(preparedList).then((res) => {
if (res.code != 200) {
throw new Error("药品发药失败");
throw new Error(t('pharmacy.msgDispenseFailed'));
}
return res;
})
@@ -1273,12 +1275,12 @@ function submitMedicine(saveList) {
}
})
.then((response) => {
proxy.$modal.msgSuccess("发药成功");
proxy.$modal.msgSuccess(t('pharmacy.msgDispenseSuccess'));
// 重新获取数据
getMedicineList(currentRow.value.encounterId);
})
.catch((error) => {
proxy.$modal.msgError('发药失败: ' + error.message);
proxy.$modal.msgError(t('pharmacy.msgDispenseFailed') + ': ' + error.message);
});
} else if (projectTypeCode.value == 2) {
let preparationList = saveList.filter((item) => {
@@ -1296,7 +1298,7 @@ function submitMedicine(saveList) {
prepareMedicion(preparationList).then((res) => {
if (res.code == 200) {
updateMedicion(preparationList).then((response) => {
proxy.$modal.msgSuccess('发药成功');
proxy.$modal.msgSuccess(t('pharmacy.msgDispenseSuccess'));
getMedicineList(currentRow.value.encounterId);
});
}
@@ -1320,7 +1322,7 @@ function validInventory(row, item) {
quantity = quantity * item.partPercent;
}
if (quantity > item.inventoryQuantity) {
proxy.$modal.msgError('当前批次库存不足');
proxy.$modal.msgError(t('pharmacy.msgInsufficientStock'));
return;
}
}
@@ -1336,10 +1338,10 @@ function handleQuantity(row) {
});
if (totalQuantity > row.requestQuantity) {
couldSave.value = false;
proxy.$modal.msgError('发药数量不能大于总数量');
proxy.$modal.msgError(t('pharmacy.msgQtyExceedsTotal'));
} else if (totalQuantity < row.requestQuantity) {
couldSave.value = false;
proxy.$modal.msgError('发药数量不能小于总数量');
proxy.$modal.msgError(t('pharmacy.msgQtyBelowTotal'));
} else {
couldSave.value = true;
}
@@ -1428,7 +1430,7 @@ function handleBatch(row) {
};
});
} else {
proxy.$modal.msgWarning('未选择要发药的项目,请重新选择,发药失败');
proxy.$modal.msgWarning(t('pharmacy.msgSelectDispenseItem'));
return;
}
}
@@ -1456,7 +1458,7 @@ async function handleConfirm() {
return;
}
const loading = ElLoading.service({text: "作废中..."});
const loading = ElLoading.service({text: t('pharmacy.voiding')});
try {
const params = buildParams();
@@ -1472,10 +1474,10 @@ async function handleConfirm() {
// 分离验证逻辑
function validate() {
if (!notPerformedReasonEnum.value) {
return {success: false, message: "请选择作废原因"};
return {success: false, message: t('pharmacy.msgSelectVoidReason')};
}
if (!selectedRow.value) {
return {success: false, message: "未选择数据"};
return {success: false, message: t('pharmacy.msgNoDataSelected')};
}
return {success: true};
}

View File

@@ -1,9 +1,9 @@
<template>
<template>
<div class="smart-triage-queue">
<!-- 顶部标题栏 -->
<div class="header-section">
<div class="header-left">
<span class="title">智能分诊排队管理 - {{ currentDeptName }}</span>
<span class="title">{{ $t('triage.title') }} - {{ currentDeptName }}</span>
</div>
<div class="header-right">
<el-button
@@ -11,13 +11,13 @@
@click="handleRefresh"
>
<el-icon><Refresh /></el-icon>
刷新
{{ $t('common.refresh') }}
</el-button>
<el-button @click="handleExit">
退出
{{ $t('triage.exit') }}
</el-button>
<el-button @click="handleConfig">
后台配置
{{ $t('triage.backendConfig') }}
</el-button>
</div>
</div>
@@ -27,7 +27,7 @@
<!-- 左侧智能候选池 -->
<div class="left-panel">
<div class="panel-header">
<span class="panel-title"> 智能候选池 (已签到未入队)</span>
<span class="panel-title"> {{ $t('triage.candidatePoolTitle') }}</span>
</div>
<div class="table-container">
<vxe-table
@@ -45,43 +45,43 @@
/>
<vxe-column
field="sequenceNo"
title="序号"
:title="$t('triage.seqNo')"
width="80"
align="center"
/>
<vxe-column
field="patientName"
title="患者"
:title="$t('triage.patient')"
width="100"
align="center"
/>
<vxe-column
field="age"
title="年龄"
:title="$t('triage.age')"
width="80"
align="center"
/>
<vxe-column
field="appointmentType"
title="号别"
:title="$t('triage.ticketType')"
width="100"
align="center"
/>
<vxe-column
field="room"
title="诊室"
:title="$t('triage.room')"
width="120"
align="center"
/>
<vxe-column
field="doctor"
title="医生"
:title="$t('triage.doctor')"
width="120"
align="center"
/>
<vxe-column
field="matchingRule"
title="命中规则"
:title="$t('triage.matchedRule')"
min-width="150"
align="center"
/>
@@ -93,14 +93,14 @@
:disabled="selectedCandidates.length === 0 || isQueryingHistory"
@click="handleAddToQueue"
>
加入队列 >>
{{ $t('triage.addToQueue') }}
</el-button>
<el-button
type="primary"
:disabled="filteredCandidatePoolList.length === 0 || isQueryingHistory"
@click="handleAddAllToQueue"
>
一键加入队列
{{ $t('triage.addAllToQueue') }}
</el-button>
</div>
</div>
@@ -108,12 +108,12 @@
<!-- 右侧智能队列 -->
<div class="right-panel">
<div class="panel-header">
<span class="panel-title"> 智能队列 (全科)</span>
<span class="panel-title"> {{ $t('triage.queueTitle') }}</span>
<div class="history-query">
<el-date-picker
v-model="queryDate"
type="date"
placeholder="选择日期"
:placeholder="$t('triage.selectDate')"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
size="small"
@@ -124,19 +124,19 @@
size="small"
@click="handleHistoryQuery"
>
查询
{{ $t('triage.query') }}
</el-button>
<el-button
size="small"
@click="handleTodayQuery"
>
今天
{{ $t('triage.today') }}
</el-button>
</div>
</div>
<div class="table-container">
<vxe-table
:data="filteredQueueList"
:data="translatedQueueList"
stripe
border
height="100%"
@@ -146,49 +146,49 @@
>
<vxe-column
field="queueOrder"
title="队序"
:title="$t('triage.queueOrder')"
width="80"
align="center"
/>
<vxe-column
field="patientName"
title="患者"
:title="$t('triage.patient')"
width="100"
align="center"
/>
<vxe-column
field="appointmentType"
title="号别"
:title="$t('triage.ticketType')"
width="100"
align="center"
/>
<vxe-column
field="room"
title="诊室"
:title="$t('triage.room')"
width="120"
align="center"
/>
<vxe-column
field="doctor"
title="医生"
:title="$t('triage.doctor')"
width="120"
align="center"
/>
<vxe-column
field="waitingTime"
title="等待"
:title="$t('triage.waiting')"
width="100"
align="center"
/>
<vxe-column
field="status"
title="状态"
:title="$t('triage.status')"
width="100"
align="center"
>
<template #default="scope">
<el-tag :type="getStatusTagType(scope.row.status)">
{{ scope.row.status }}
{{ scope.row.displayStatus }}
</el-tag>
</template>
</vxe-column>
@@ -202,7 +202,7 @@
size="small"
@click="handleRemoveFromQueue"
>
&lt;&lt; 移出队列
&lt;&lt; {{ $t('triage.removeFromQueue') }}
</el-button>
<el-button
type="info"
@@ -231,7 +231,7 @@
<div class="filter-section">
<div class="filter-left">
<div class="filter-label">
诊室快速过滤栏
{{ $t('triage.roomFilterTitle') }}
</div>
<div class="filter-button-wrapper">
<el-button
@@ -239,7 +239,7 @@
size="small"
@click="selectedRoom = 'all'"
>
全部
{{ $t('triage.all') }}
</el-button>
<el-button
v-for="room in uniqueRooms"
@@ -258,14 +258,14 @@
size="small"
@click="showOnlyWaiting = true"
>
只显示等待
{{ $t('triage.showOnlyWaiting') }}
</el-button>
<el-button
:type="!showOnlyWaiting ? 'primary' : ''"
size="small"
@click="showOnlyWaiting = false"
>
显示全部状态
{{ $t('triage.showAllStatus') }}
</el-button>
</div>
</div>
@@ -273,11 +273,11 @@
<!-- 叫号控制板 -->
<div class="call-control-section">
<div class="call-control-label">
叫号控制板
{{ $t('triage.callPanelTitle') }}
</div>
<div class="call-control-content">
<div class="current-call-display">
当前呼叫: {{ currentCall.number }} {{ currentCall.name }} 诊室: {{ currentCall.room }}
{{ $t('triage.currentCall') }}: {{ currentCall.number }} {{ currentCall.name }} {{ $t('triage.room') }}: {{ currentCall.room }}
</div>
<div class="control-buttons">
<el-button
@@ -285,35 +285,35 @@
:disabled="isQueryingHistory"
@click="handleSelectCall"
>
选呼
{{ $t('triage.selectCall') }}
</el-button>
<el-button
type="success"
:disabled="isQueryingHistory"
@click="handleNextPatient"
>
下一患者
{{ $t('triage.nextPatient') }}
</el-button>
<el-button
type="warning"
:disabled="isQueryingHistory"
@click="handleSkip"
>
跳过
{{ $t('triage.skip') }}
</el-button>
<el-button
type="primary"
:disabled="isQueryingHistory"
@click="handleComplete"
>
完成
{{ $t('triage.complete') }}
</el-button>
<el-button
type="info"
:disabled="isQueryingHistory"
@click="handleRequeue"
>
过号重排
{{ $t('triage.requeue') }}
</el-button>
</div>
</div>
@@ -322,17 +322,17 @@
<!-- LED显示 -->
<div class="led-section">
<div class="led-label">
LED:
{{ $t('triage.ledLabel') }}:
</div>
<div class="led-display">
[{{ currentCall.number }}]{{ currentCall.name }}请到{{ currentCall.room }}({{ callType }})
[{{ currentCall.number }}]{{ currentCall.name }}{{ $t('triage.pleaseGoTo') }}{{ currentCall.room }}({{ callTypeDisplay }})
</div>
</div>
<!-- 语音提示 -->
<div class="voice-section">
<span class="voice-label">语音:</span>
<span class="voice-text">{{ currentCall.number }}{{ currentCall.name }}{{ currentCall.room }}({{ callType }})</span>
<span class="voice-label">{{ $t('triage.voiceLabel') }}:</span>
<span class="voice-text">{{ $t('triage.voiceCallText', { number: currentCall.number, name: currentCall.name, room: currentCall.room, type: callTypeDisplay }) }}</span>
</div>
</div>
@@ -345,23 +345,23 @@
<template #header>
<div class="config-dialog-header">
<div class="config-dialog-title">
智能分诊规则引擎配置 - 心内科
{{ $t('triage.ruleConfigTitle') }}
</div>
<div class="config-topbar-actions">
<el-button
type="primary"
@click="handleAddRule"
>
新增规则
{{ $t('triage.addRule') }}
</el-button>
<el-button
type="primary"
@click="handleSaveAllRules"
>
保存全部
{{ $t('triage.saveAll') }}
</el-button>
<el-button @click="handleTestRule">
测试规则
{{ $t('triage.testRule') }}
</el-button>
</div>
</div>
@@ -378,7 +378,7 @@
@click="handleSelectRule(idx)"
>
<div class="rule-title">
规则{{ idx + 1 }}
{{ $t('triage.rule') }}{{ idx + 1 }}
</div>
<div class="rule-sub">
prio={{ item.priority }}
@@ -391,13 +391,13 @@
size="small"
@click.stop="handleSelectRule(idx)"
>
编辑
{{ $t('common.edit') }}
</el-button>
<el-button
size="small"
@click.stop="handleDeleteRule(idx)"
>
删除
{{ $t('common.delete') }}
</el-button>
<el-button
size="small"
@@ -424,43 +424,43 @@
class="config-form"
>
<el-form-item
label="规则名称:"
:label="$t('triage.ruleName') + ':'"
required
>
<el-input
v-model="ruleForm.name"
placeholder="请输入规则名称"
:placeholder="$t('triage.placeholderRuleName')"
/>
</el-form-item>
<el-form-item label="科室:">
<el-form-item :label="$t('triage.department') + ':'">
<el-select
v-model="ruleForm.dept"
class="config-fullwidth"
disabled
>
<el-option
label="心内科"
:label="$t('triage.cardiology')"
value="心内科"
/>
</el-select>
</el-form-item>
<el-form-item label="规则描述:">
<el-form-item :label="$t('triage.ruleDesc') + ':'">
<el-input
v-model="ruleForm.desc"
placeholder="请输入规则描述"
:placeholder="$t('triage.placeholderRuleDesc')"
/>
</el-form-item>
<el-form-item
label="优先级:"
:label="$t('triage.priority') + ':'"
required
>
<el-input v-model="ruleForm.priority" />
</el-form-item>
<el-form-item label="周几生效:">
<el-form-item :label="$t('triage.weekDayActive') + ':'">
<el-checkbox-group v-model="ruleForm.weeks">
<el-checkbox
v-for="w in weekOptions"
@@ -472,7 +472,7 @@
</el-checkbox-group>
</el-form-item>
<el-form-item label="条件表达式(JSON):">
<el-form-item :label="$t('triage.conditionExpr') + ':'">
<el-input
v-model="ruleForm.expr"
type="textarea"
@@ -483,10 +483,10 @@
<div class="config-inline-actions">
<el-button @click="handleQuickGenerate">
快速生成器
{{ $t('triage.quickGenerator') }}
</el-button>
<el-button @click="handleValidateRule">
语法检查
{{ $t('triage.syntaxCheck') }}
</el-button>
</div>
</el-form>
@@ -499,10 +499,10 @@
type="primary"
@click="handleSaveCurrentRule"
>
保存
{{ $t('common.save') }}
</el-button>
<el-button @click="configDialogVisible = false">
取消
{{ $t('common.cancel') }}
</el-button>
</div>
</template>
@@ -511,7 +511,7 @@
<!-- 快速生成器对话框 -->
<el-dialog
v-model="quickGeneratorDialogVisible"
title="快速生成器"
:title="$t('triage.quickGenerator')"
width="600px"
:close-on-click-modal="false"
>
@@ -519,7 +519,7 @@
:model="quickGeneratorForm"
label-width="120px"
>
<el-form-item label="年龄条件:">
<el-form-item :label="$t('triage.ageCondition') + ':'">
<div style="display: flex; align-items: center; gap: 10px;">
<el-select
v-model="quickGeneratorForm.ageOperator"
@@ -551,94 +551,94 @@
:min="0"
:max="150"
:precision="0"
placeholder="年龄"
:placeholder="$t('triage.age')"
style="width: 150px;"
/>
<el-button
type="link"
@click="quickGeneratorForm.ageOperator = null; quickGeneratorForm.ageValue = null"
>
清除
{{ $t('triage.clear') }}
</el-button>
</div>
</el-form-item>
<el-form-item label="号别/类型:">
<el-form-item :label="$t('triage.ticketTypeLabel') + ':'">
<el-select
v-model="quickGeneratorForm.regType"
placeholder="请选择号别"
:placeholder="$t('triage.placeholderSelectTicketType')"
clearable
style="width: 100%"
>
<el-option
label="专家"
:label="$t('triage.expert')"
value="专家"
/>
<el-option
label="普通"
:label="$t('triage.normal')"
value="普通"
/>
<el-option
label="特需"
:label="$t('triage.specialNeeds')"
value="特需"
/>
<el-option
label="急诊"
:label="$t('triage.emergency')"
value="急诊"
/>
</el-select>
</el-form-item>
<el-form-item label="科室:">
<el-form-item :label="$t('triage.department') + ':'">
<el-select
v-model="quickGeneratorForm.dept"
placeholder="请选择科室"
:placeholder="$t('triage.placeholderSelectDept')"
clearable
style="width: 100%"
>
<el-option
label="心内科"
:label="$t('triage.cardiology')"
value="心内科"
/>
<el-option
label="心外科"
:label="$t('triage.cardiacSurgery')"
value="心外科"
/>
<el-option
label="神经内科"
:label="$t('triage.neurology')"
value="神经内科"
/>
</el-select>
</el-form-item>
<el-form-item label="医生:">
<el-form-item :label="$t('triage.doctor') + ':'">
<el-input
v-model="quickGeneratorForm.doctor"
placeholder="请输入医生姓名(支持模糊匹配)"
:placeholder="$t('triage.placeholderDoctor')"
clearable
/>
</el-form-item>
<el-form-item label="自定义条件:">
<el-form-item :label="$t('triage.customCondition') + ':'">
<el-input
v-model="quickGeneratorForm.customKey"
placeholder="字段名gender"
:placeholder="$t('triage.placeholderFieldName')"
style="width: 150px; margin-right: 10px;"
/>
<el-input
v-model="quickGeneratorForm.customValue"
placeholder="字段值(如:男)"
:placeholder="$t('triage.placeholderFieldValue')"
style="width: 200px;"
/>
<el-button
type="link"
@click="quickGeneratorForm.customKey = ''; quickGeneratorForm.customValue = ''"
>
清除
{{ $t('triage.clear') }}
</el-button>
</el-form-item>
<el-form-item label="预览JSON:">
<el-form-item :label="$t('triage.previewJson') + ':'">
<el-input
:value="previewJson"
type="textarea"
@@ -652,13 +652,13 @@
<template #footer>
<div style="text-align: right;">
<el-button @click="quickGeneratorDialogVisible = false">
取消
{{ $t('common.cancel') }}
</el-button>
<el-button
type="primary"
@click="handleApplyQuickGenerate"
>
应用
{{ $t('triage.apply') }}
</el-button>
</div>
</template>
@@ -668,8 +668,10 @@
<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { useI18n } from 'vue-i18n'
import useUserStore from '@/store/modules/user'
const { t } = useI18n()
const userStore = useUserStore()
import { Refresh } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
@@ -772,19 +774,47 @@ const quickGeneratorForm = reactive({
customKey: '', // 自定义字段名
customValue: '' // 自定义字段值
})
const weekOptions = [
{ label: '一', value: '1' },
{ label: '二', value: '2' },
{ label: '三', value: '3' },
{ label: '四', value: '4' },
{ label: '五', value: '5' },
{ label: '六', value: '6' },
{ label: '日', value: '0' }
]
const weekOptions = computed(() => [
{ label: t('triage.weekMon'), value: '1' },
{ label: t('triage.weekTue'), value: '2' },
{ label: t('triage.weekWed'), value: '3' },
{ label: t('triage.weekThu'), value: '4' },
{ label: t('triage.weekFri'), value: '5' },
{ label: t('triage.weekSat'), value: '6' },
{ label: t('triage.weekSun'), value: '0' }
])
// 叫号类型
const callType = ref('选呼')
const callTypeDisplay = computed(() => {
const map = {
'选呼': t('triage.selectCall'),
'下一患者': t('triage.nextPatient'),
'跳过': t('triage.skip'),
'完成': t('triage.complete'),
'过号重排': t('triage.requeue'),
'刷新': t('common.refresh')
}
return map[callType.value] || callType.value
})
const translatedQueueList = computed(() => {
const statusMap = {
'等待': t('triage.statusWaiting'),
'叫号中': t('triage.statusCalling'),
'就诊中': t('triage.statusInConsultation'),
'已完成': t('triage.statusCompleted'),
'跳过': t('triage.statusSkipped'),
'已退费': t('triage.statusRefunded'),
'已随访': t('triage.statusFollowUp')
}
return filteredQueueList.value.map(item => ({
...item,
displayStatus: statusMap[item.status] || item.status
}))
})
const syncCurrentCallFromQueue = () => {
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
if (!calling) {
@@ -1059,7 +1089,7 @@ const loadDataFromApi = async () => {
// 同步当前呼叫(队列从 DB 加载后已同步;这里再兜底一次)
syncCurrentCallFromQueue()
console.log('【心内科】数据加载完成:候选池', originalCandidatePoolList.value.length, '条,队列', originalQueueList.value.length, '条')
ElMessage.success(`${currentDeptName.value}】已从门诊挂号接口加载数据`)
ElMessage.success(t('triage.msgDataLoaded'))
} catch (e) {
console.error('【心内科】loadDataFromApi 执行异常:', e)
originalCandidatePoolList.value = []
@@ -1147,7 +1177,7 @@ const handleCandidateSelectionChange = ({ records }) => {
// 加入队列(选中的候选池患者)——落库
const handleAddToQueue = async () => {
if (selectedCandidates.value.length === 0) {
ElMessage.warning('请先选择要加入队列的患者')
ElMessage.warning(t('triage.msgSelectPatientToAdd'))
return
}
@@ -1236,11 +1266,11 @@ const handleAddToQueue = async () => {
console.log('【心内科】handleAddToQueue 完成:候选池从', beforeCount, '条减少到', afterCount, '条,成功加入', added, '位')
if (added > 0) {
ElMessage.success(`成功将 ${added} 位患者加入队列(已保存)`)
ElMessage.success(t('triage.msgAddedToQueue', { count: added }))
} else if (addedEncounterIds.size > 0) {
ElMessage.warning('所选患者已在队列中,已从候选池移除')
ElMessage.warning(t('triage.msgAlreadyInQueue'))
} else {
ElMessage.warning('加入队列失败,请重试')
ElMessage.warning(t('triage.msgAddFailed'))
}
} catch (e) {
console.error('【心内科】handleAddToQueue 异常:', e)
@@ -1258,14 +1288,14 @@ const handleAddToQueue = async () => {
totalSignedIn.value = originalCandidatePoolList.value.length
selectedCandidates.value = []
}
ElMessage.error('加入队列失败(未保存)')
ElMessage.error(t('triage.msgAddFailedUnsaved'))
}
}
// 一键加入队列(所有候选池患者)——落库
const handleAddAllToQueue = async () => {
if (filteredCandidatePoolList.value.length === 0) {
ElMessage.warning('候选池中没有患者')
ElMessage.warning(t('triage.msgNoCandidates'))
return
}
@@ -1354,11 +1384,11 @@ const handleAddAllToQueue = async () => {
console.log('【心内科】handleAddAllToQueue 完成:候选池从', beforeCount, '条减少到', afterCount, '条,成功加入', added, '位')
if (added > 0) {
ElMessage.success(`成功将 ${added} 位患者加入队列(已保存)`)
ElMessage.success(t('triage.msgAddedToQueue', { count: added }))
} else if (addedEncounterIds.size > 0) {
ElMessage.warning('所有候选池患者已在队列中,已从候选池移除')
ElMessage.warning(t('triage.msgAllAlreadyInQueue'))
} else {
ElMessage.warning('一键加入失败,请重试')
ElMessage.warning(t('triage.msgAddAllFailed'))
}
} catch (e) {
console.error('【心内科】handleAddAllToQueue 异常:', e)
@@ -1376,21 +1406,21 @@ const handleAddAllToQueue = async () => {
totalSignedIn.value = originalCandidatePoolList.value.length
selectedCandidates.value = []
}
ElMessage.error('一键加入失败(未保存)')
ElMessage.error(t('triage.msgAddAllFailedUnsaved'))
}
}
// 移出队列——落库
const handleRemoveFromQueue = async () => {
if (!selectedQueueRow.value) {
ElMessage.warning('请先选择要移出队列的患者')
ElMessage.warning(t('triage.msgSelectPatientToRemove'))
return
}
try {
const row = selectedQueueRow.value
if (!row.id) {
ElMessage.warning('该队列项缺少ID无法保存删除请先刷新页面')
ElMessage.warning(t('triage.msgMissingIdRemove'))
return
}
@@ -1404,10 +1434,10 @@ const handleRemoveFromQueue = async () => {
await loadDataFromApi()
console.log('【心内科】移出队列完成,患者应已重新出现在候选池中')
ElMessage.success(`已将 ${patientName} 移出队列,患者已重新出现在候选池中(已保存)`)
ElMessage.success(t('triage.msgRemovedFromQueue', { name: patientName }))
} catch (e) {
console.error('【心内科】handleRemoveFromQueue 异常:', e)
ElMessage.error('移出队列失败(未保存)')
ElMessage.error(t('triage.msgRemoveFailed'))
}
}
@@ -1433,16 +1463,16 @@ const canMoveDown = computed(() => {
const handleMoveUp = async () => {
if (!selectedQueueRow.value || !canMoveUp.value) return
if (!selectedQueueRow.value.id) {
ElMessage.warning('该队列项缺少ID无法保存排序请先刷新页面')
ElMessage.warning(t('triage.msgMissingIdSort'))
return
}
try {
await adjustQueueOrder({ id: selectedQueueRow.value.id, direction: 'up' })
await loadDataFromApi()
ElMessage.success('队列顺序已调整(已保存)')
ElMessage.success(t('triage.msgOrderAdjusted'))
} catch (e) {
console.error('【心内科】handleMoveUp 异常:', e)
ElMessage.error('队列顺序调整失败(未保存)')
ElMessage.error(t('triage.msgOrderAdjustFailed'))
}
}
@@ -1450,16 +1480,16 @@ const handleMoveUp = async () => {
const handleMoveDown = async () => {
if (!selectedQueueRow.value || !canMoveDown.value) return
if (!selectedQueueRow.value.id) {
ElMessage.warning('该队列项缺少ID无法保存排序请先刷新页面')
ElMessage.warning(t('triage.msgMissingIdSort'))
return
}
try {
await adjustQueueOrder({ id: selectedQueueRow.value.id, direction: 'down' })
await loadDataFromApi()
ElMessage.success('队列顺序已调整(已保存)')
ElMessage.success(t('triage.msgOrderAdjusted'))
} catch (e) {
console.error('【心内科】handleMoveDown 异常:', e)
ElMessage.error('队列顺序调整失败(未保存)')
ElMessage.error(t('triage.msgOrderAdjustFailed'))
}
}
@@ -1533,19 +1563,19 @@ const handleRefresh = async () => {
stopWaitingTimer()
startWaitingTimer()
ElMessage.success('已刷新(已从数据库恢复队列)')
ElMessage.success(t('triage.msgRefreshed'))
}
// 历史队列查询
const handleHistoryQuery = async () => {
if (!queryDate.value) {
ElMessage.warning('请选择查询日期')
ElMessage.warning(t('triage.msgSelectQueryDate'))
return
}
console.log('【心内科】历史队列查询:', queryDate.value)
await loadQueueFromDb(queryDate.value)
if (isQueryingHistory.value) {
ElMessage.success(`已加载 ${queryDate.value} 的队列数据`)
ElMessage.success(t('triage.msgLoadedHistory', { date: queryDate.value }))
}
}
@@ -1553,12 +1583,12 @@ const handleHistoryQuery = async () => {
const handleTodayQuery = async () => {
queryDate.value = getTodayStr()
await loadQueueFromDb(getTodayStr())
ElMessage.success('已切换到今天队列')
ElMessage.success(t('triage.msgSwitchedToToday'))
}
// 退出
const handleExit = () => {
ElMessage.info('退出功能待实现')
ElMessage.info(t('triage.msgExitNotImpl'))
// TODO: 实现退出逻辑
}
@@ -1585,24 +1615,24 @@ const handleConfig = () => {
// 选呼——落库
const handleSelectCall = async () => {
if (!selectedQueueRow.value) {
ElMessage.warning('请先在右侧队列中选择一个患者')
ElMessage.warning(t('triage.msgSelectPatientInQueue'))
return
}
try {
callType.value = '选呼'
if (!selectedQueueRow.value.id) {
ElMessage.warning('该队列项缺少ID无法保存选呼请先刷新页面')
ElMessage.warning(t('triage.msgMissingIdSelectCall'))
return
}
// 检查患者状态,只有"等待"状态才能选呼
if (selectedQueueRow.value.status !== '等待') {
if (selectedQueueRow.value.status === '叫号中') {
ElMessage.info('该患者已经是"叫号中"状态')
ElMessage.info(t('triage.msgAlreadyCalling'))
return
} else {
ElMessage.warning('只能选呼"等待"状态的患者,当前患者状态为:"' + selectedQueueRow.value.status + '"')
ElMessage.warning(t('triage.msgCanOnlyCallWaiting', { status: selectedQueueRow.value.status }))
return
}
}
@@ -1620,13 +1650,13 @@ const handleSelectCall = async () => {
// 统计当前"叫号中"的患者数量
const callingCount = originalQueueList.value.filter(i => i.status === '叫号中').length
if (callingCount > 1) {
ElMessage.success(`已选呼(已保存),当前共有 ${callingCount} 位患者处于"叫号中"状态`)
ElMessage.success(t('triage.msgSelectCalledWithCount', { count: callingCount }))
} else {
ElMessage.success('已选呼(已保存)')
ElMessage.success(t('triage.msgSelectCalledSingle'))
}
} catch (e) {
console.error('【心内科】handleSelectCall 异常:', e)
ElMessage.error('选呼失败(未保存)')
ElMessage.error(t('triage.msgSelectCallFailed'))
}
}
@@ -1655,11 +1685,11 @@ const handleNextPatient = async () => {
await nextPatient(reqData)
selectedQueueRow.value = null
await loadDataFromApi()
ElMessage.success('已呼叫下一位(已保存)')
ElMessage.success(t('triage.msgNextCalled'))
} catch (e) {
console.error('【心内科】handleNextPatient 异常:', e)
// 从错误对象中提取错误消息
const errorMsg = e?.message || e?.response?.data?.msg || '当前范围内没有"等待"的患者'
const errorMsg = e?.message || e?.response?.data?.msg || t('triage.msgNoWaitingPatient')
ElMessage.warning(errorMsg)
}
}
@@ -1685,11 +1715,11 @@ const handleSkip = async () => {
await skipPatient(reqData)
selectedQueueRow.value = null
await loadDataFromApi()
ElMessage.success('已跳过(已保存)')
ElMessage.success(t('triage.msgSkipped'))
} catch (e) {
console.error('【心内科】handleSkip 异常:', e)
// 从错误对象中提取错误消息
const errorMsg = e?.message || e?.response?.data?.msg || '当前没有"叫号中"的患者'
const errorMsg = e?.message || e?.response?.data?.msg || t('triage.msgNoCallingPatient')
ElMessage.warning(errorMsg)
}
}
@@ -1715,11 +1745,11 @@ const handleComplete = async () => {
await completeCall(reqData)
selectedQueueRow.value = null
await loadDataFromApi()
ElMessage.success('已完成(已保存)')
ElMessage.success(t('triage.msgCompleted'))
} catch (e) {
console.error('【心内科】handleComplete 异常:', e)
// 从错误对象中提取错误消息
const errorMsg = e?.message || e?.response?.data?.msg || '当前没有"叫号中"的患者'
const errorMsg = e?.message || e?.response?.data?.msg || t('triage.msgNoCallingPatient')
ElMessage.warning(errorMsg)
}
}
@@ -1746,13 +1776,13 @@ const handleRequeue = async () => {
// 如果执行到这里,说明操作成功
selectedQueueRow.value = null
await loadDataFromApi()
ElMessage.success('已过号重排(已保存)')
ElMessage.success(t('triage.msgRequeued'))
} catch (e) {
console.error('【心内科】handleRequeue 异常:', e)
// 从错误对象中提取错误消息
// 注意:当后端返回 R.fail() 时code=500响应拦截器会 Promise.reject(new Error(msg))
// 所以错误消息在 e.message 中
const errorMsg = e?.message || e?.response?.data?.msg || '当前没有等待中的患者'
const errorMsg = e?.message || e?.response?.data?.msg || t('triage.msgNoWaitingPatientRequeue')
ElMessage.warning(errorMsg)
// 失败时不要刷新数据,避免显示错误的状态
// await loadDataFromApi() // 注释掉,避免刷新数据
@@ -1768,11 +1798,11 @@ const handleSelectRule = (index) => {
// 后台配置:保存当前规则到列表
const persistRuleForm = () => {
if (!ruleForm.name || !ruleForm.priority) {
ElMessage.warning('请填写规则名称和优先级')
ElMessage.warning(t('triage.msgFillRuleNameAndPriority'))
return false
}
if (!Array.isArray(ruleForm.weeks) || ruleForm.weeks.length === 0) {
ElMessage.warning('请选择生效周几')
ElMessage.warning(t('triage.msgSelectWeekDays'))
return false
}
const parsed = tryParseExpr(ruleForm.expr)
@@ -1802,7 +1832,7 @@ const tryParseExpr = (expr) => {
JSON.parse(expr || '{}')
return true
} catch (e) {
ElMessage.error('条件表达式 JSON 语法错误')
ElMessage.error(t('triage.msgJsonSyntaxError'))
return null
}
}
@@ -1812,7 +1842,7 @@ const handleAddRule = () => {
const ok = persistRuleForm()
if (!ok) return
const newRule = {
name: '新规则',
name: t('triage.newRule'),
dept: '心内科',
desc: '',
priority: rules.value.length * 10 + 10,
@@ -1862,7 +1892,7 @@ const handleRuleMoveDown = (index) => {
const handleSaveCurrentRule = () => {
const ok = persistRuleForm()
if (ok) {
ElMessage.success('当前规则已保存')
ElMessage.success(t('triage.msgRuleSaved'))
}
}
@@ -1871,14 +1901,14 @@ const handleSaveAllRules = () => {
const ok = persistRuleForm()
if (!ok) return
// TODO: 调用后端保存接口
ElMessage.success('全部规则已保存(前端模拟)')
ElMessage.success(t('triage.msgAllRulesSaved'))
}
// 后台配置:语法检查
const handleValidateRule = () => {
const ok = tryParseExpr(ruleForm.expr)
if (ok) {
ElMessage.success('语法检查通过')
ElMessage.success(t('triage.msgSyntaxCheckPassed'))
}
}
@@ -1978,7 +2008,7 @@ const handleApplyQuickGenerate = () => {
// 检查是否至少有一个条件
if (Object.keys(conditions).length === 0) {
ElMessage.warning('请至少设置一个条件')
ElMessage.warning(t('triage.msgAtLeastOneCondition'))
return
}
@@ -1988,14 +2018,14 @@ const handleApplyQuickGenerate = () => {
// 关闭对话框
quickGeneratorDialogVisible.value = false
ElMessage.success('条件表达式已生成并应用')
ElMessage.success(t('triage.msgConditionApplied'))
}
// 后台配置:测试规则(占位)
const handleTestRule = () => {
const ok = tryParseExpr(ruleForm.expr)
if (!ok) return
ElMessage.info('测试规则功能待接入后端,当前为占位')
ElMessage.info(t('triage.msgTestRulePlaceholder'))
}
// 组件挂载