feat(i18n): migrate menu, dict type, registration, doctor station, common components to vue-i18n

This commit is contained in:
2026-06-24 15:38:28 +08:00
parent 88912d26bf
commit ded899d45c
31 changed files with 1158 additions and 3453 deletions

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_16_09_56_取消提交了更改_[更改]" date="1781574986508" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_09_56_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/16 09:56 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_09_56_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_16_10_44_取消提交了更改_[更改]" date="1781577901658" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_10_44_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/16 10:44 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_10_44_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_16_13_36_取消提交了更改_[更改]" date="1781588195703" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_13_36_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/16 13:36 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_13_36_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_16_13_38_取消提交了更改_[更改]" date="1781588299786" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_13_38_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/16 13:38 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_13_38_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_16_15_24_取消提交了更改_[更改]" date="1781594661495" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_15_24_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/16 15:24 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_15_24_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_16_16_12_取消提交了更改_[更改]" date="1781597537348" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_16_12_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/16 16:12 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_16_16_12_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

View File

@@ -1,8 +0,0 @@
<changelist name="在进行更新之前于_2026_6_17_08_41_取消提交了更改_[更改]" date="1781656871923" recycled="true" deleted="true">
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_17_08_41_取消提交了更改_[更改]/shelved.patch" />
<option name="DESCRIPTION" value="在进行更新之前于 2026/6/17 08:41 取消提交了更改 [更改]" />
<binary>
<option name="AFTER_PATH" value="MD/HEALTHLINK_HIS_PRICING_v0.1.docx" />
<option name="SHELVED_PATH" value="$PROJECT_DIR$/.idea/shelf/在进行更新之前于_2026_6_17_08_41_取消提交了更改_[更改]/HEALTHLINK_HIS_PRICING_v0.1.docx" />
</binary>
</changelist>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -16,7 +16,7 @@
>
<!-- 上传按钮 -->
<el-button type="primary">
选取文件
{{ t('component.upload.selectFile') }}
</el-button>
</el-upload>
<!-- 上传提示 -->
@@ -24,14 +24,14 @@
v-if="showTip"
class="el-upload__tip"
>
请上传
{{ t('component.upload.tipPrefix') }}
<template v-if="fileSize">
大小不超过 <b style="color: #EF4444">{{ fileSize }}MB</b>
{{ t('component.upload.tipSizeLimit') }} <b style="color: #EF4444">{{ fileSize }}MB</b>
</template>
<template v-if="fileType">
格式为 <b style="color: #EF4444">{{ fileType.join("/") }}</b>
{{ t('component.upload.tipFormat') }} <b style="color: #EF4444">{{ fileType.join("/") }}</b>
</template>
的文件
{{ t('component.upload.tipSuffix') }}
</div>
<!-- 文件列表 -->
<transition-group
@@ -57,7 +57,7 @@
type="danger"
@click="handleDelete(index)"
>
删除
{{ t('component.upload.delete') }}
</el-link>
</div>
</li>
@@ -68,8 +68,11 @@
<script setup>
import {computed, ref, watch} from 'vue';
import {getToken} from "@/utils/auth";
import {useI18n} from 'vue-i18n';
import modal from '@/plugins/modal';
const {t} = useI18n();
const props = defineProps({
modelValue: [String, Object, Array],
// 数量限制
@@ -133,7 +136,7 @@ function handleBeforeUpload(file) {
const fileExt = fileName[fileName.length - 1];
const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
if (!isTypeOk) {
modal.msgError(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
modal.msgError(t('component.upload.fileFormatError', { types: props.fileType.join("/") }));
return false;
}
}
@@ -141,23 +144,23 @@ function handleBeforeUpload(file) {
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`);
modal.msgError(t('component.upload.fileSizeError', { size: props.fileSize }));
return false;
}
}
modal.loading("正在上传文件,请稍候...");
modal.loading(t('component.upload.uploadingFile'));
number.value++;
return true;
}
// 文件个数超出
function handleExceed() {
modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
modal.msgError(t('component.upload.countError', { limit: props.limit }));
}
// 上传失败
function handleUploadError(err) {
modal.msgError("上传文件失败");
modal.msgError(t('component.upload.uploadFileFailed'));
}
// 上传成功回调

View File

@@ -26,19 +26,19 @@
v-if="showTip"
class="el-upload__tip"
>
请上传
{{ t('component.upload.tipPrefix') }}
<template v-if="fileSize">
大小不超过 <b style="color: #EF4444">{{ fileSize }}MB</b>
{{ t('component.upload.tipSizeLimit') }} <b style="color: #EF4444">{{ fileSize }}MB</b>
</template>
<template v-if="fileType">
格式为 <b style="color: #EF4444">{{ fileType.join("/") }}</b>
{{ t('component.upload.tipFormat') }} <b style="color: #EF4444">{{ fileType.join("/") }}</b>
</template>
的文件
{{ t('component.upload.tipSuffix') }}
</div>
<el-dialog
v-model="dialogVisible"
title="预览"
:title="t('component.upload.preview')"
width="800px"
teleported
>
@@ -53,8 +53,11 @@
<script setup>
import {getToken} from "@/utils/auth";
import {computed, ref, watch} from 'vue';
import {useI18n} from 'vue-i18n';
import modal from '@/plugins/modal';
const {t} = useI18n();
const props = defineProps({
modelValue: [String, Object, Array],
// 图片数量限制
@@ -132,24 +135,24 @@ function handleBeforeUpload(file) {
}
if (!isImg) {
modal.msgError(
`文件格式不正确, 请上传${props.fileType.join("/")}图片格式文件!`
t('component.upload.imageFormatError', { types: props.fileType.join("/") })
);
return false;
}
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`);
modal.msgError(t('component.upload.fileSizeError', { size: props.fileSize }));
return false;
}
}
modal.loading("正在上传图片,请稍候...");
modal.loading(t('component.upload.uploadingImage'));
number.value++;
}
// 文件个数超出
function handleExceed() {
modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`);
modal.msgError(t('component.upload.countError', { limit: props.limit }));
}
// 上传成功回调
@@ -189,7 +192,7 @@ function uploadedSuccessfully() {
// 上传失败
function handleUploadError() {
modal.msgError("上传图片失败");
modal.msgError(t('component.upload.uploadImageFailed'));
modal.closeLoading();
}

View File

@@ -8,7 +8,7 @@
v-if="search"
class="item"
effect="dark"
:content="showSearch ? '隐藏搜索' : '显示搜索'"
:content="showSearch ? t('component.rightToolbar.hideSearch') : t('component.rightToolbar.showSearch')"
placement="top"
>
<el-button
@@ -20,7 +20,7 @@
<el-tooltip
class="item"
effect="dark"
content="刷新"
:content="t('component.rightToolbar.refresh')"
placement="top"
>
<el-button
@@ -33,7 +33,7 @@
v-if="columns"
class="item"
effect="dark"
content="显隐列"
:content="t('component.rightToolbar.showHideColumns')"
placement="top"
>
<el-button
@@ -78,7 +78,7 @@
>
<el-transfer
v-model="value"
:titles="['显示', '隐藏']"
:titles="[t('component.rightToolbar.show'), t('component.rightToolbar.hide')]"
:data="columns"
@change="dataChange"
/>
@@ -87,6 +87,10 @@
</template>
<script setup>
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const props = defineProps({
/* 是否显示检索条件 */
showSearch: {
@@ -119,7 +123,7 @@ const emits = defineEmits(['update:showSearch', 'queryTable']);
// 显隐数据
const value = ref([]);
// 弹出层标题
const title = ref("显示/隐藏");
const title = ref(t('component.rightToolbar.showHide'));
// 是否显示弹出层
const open = ref(false);

View File

@@ -127,6 +127,35 @@
"yes": "Yes",
"no": "No"
},
"component": {
"rightToolbar": {
"hideSearch": "Hide Search",
"showSearch": "Show Search",
"refresh": "Refresh",
"showHideColumns": "Show/Hide Columns",
"showHide": "Show/Hide",
"show": "Show",
"hide": "Hide"
},
"upload": {
"selectFile": "Select File",
"selectImage": "Select Image",
"tipPrefix": "Please upload",
"tipSizeLimit": "size not exceeding",
"tipFormat": "format",
"tipSuffix": "file",
"delete": "Delete",
"preview": "Preview",
"fileFormatError": "Invalid file format, please upload {types} format files!",
"imageFormatError": "Invalid file format, please upload {types} image files!",
"fileSizeError": "File size cannot exceed {size} MB!",
"countError": "Number of files cannot exceed {limit}!",
"uploadingFile": "Uploading file, please wait...",
"uploadingImage": "Uploading image, please wait...",
"uploadFileFailed": "File upload failed",
"uploadImageFailed": "Image upload failed"
}
},
"system": {
"user": {
"userId": "User ID",
@@ -279,7 +308,43 @@
"menuHidden": "Hidden",
"menuChild": "Children",
"menuLayout": "Outer Layout",
"menuAlways": "Always Show"
"menuAlways": "Always Show",
"placeholderMenuName": "Enter menu name",
"expandCollapse": "Expand/Collapse",
"fullPath": "Full Path",
"icon": "Icon",
"isExternalLink": "External Link",
"isCache": "Cache",
"cacheYes": "Cache",
"cacheNo": "No Cache",
"routeParam": "Route Param",
"placeholderSelectParent": "Select parent menu",
"placeholderClickIcon": "Click to select icon",
"placeholderRoutePath": "Enter route path",
"placeholderComponent": "Enter component path",
"placeholderPermi": "Enter permission key",
"placeholderRouteParam": "Enter route params",
"tooltipExternalLink": "If external link, route path must start with `http(s)://`",
"tooltipRoutePath": "Route path, e.g.: `user`, external URLs must start with `http(s)://`",
"tooltipComponent": "Component path, e.g.: `system/user/index`, default in `views` directory",
"tooltipPermi": "Permission key defined in controller, e.g.: @PreAuthorize(`@ss.hasPermi('system:user:list')`)",
"tooltipRouteParam": "Default route params, e.g.: `{id: 1, name: ry}`",
"tooltipCache": "If cached, component `name` must match the route path",
"tooltipVisible": "If hidden, route won't appear in sidebar but can still be accessed",
"tooltipMenuStatus": "If disabled, route won't appear in sidebar and cannot be accessed",
"addMenu": "Add Menu",
"editMenu": "Edit Menu",
"rootCategory": "Root Category",
"valMenuNameRequired": "Menu name cannot be empty",
"valOrderNumRequired": "Menu order cannot be empty",
"valPathRequired": "Route path cannot be empty",
"routePathExists": "Route path already exists",
"cacheRefreshed": "Menu cache refreshed, list updated",
"cacheRefreshFailed": "Failed to refresh menu cache",
"deleteConfirm": "Are you sure to delete menu \"{name}\"?",
"noModuleAvailable": "{name} has no corresponding module",
"moduleAccessFailed": "{name} module is not accessible, please check permissions or contact admin",
"moduleNavigateFailed": "{name} module navigation failed"
},
"dict": {
"dictCode": "Dict Code",
@@ -318,7 +383,16 @@
"valDictLabelRequired": "Data label cannot be empty",
"valDictValueRequired": "Data value cannot be empty",
"valDictSortRequired": "Sort order cannot be empty",
"deleteConfirm": "Are you sure to delete dict data \"{id}\"?"
"deleteConfirm": "Are you sure to delete dict data \"{id}\"?",
"placeholderDictName": "Enter dict name",
"placeholderDictType": "Enter dict type",
"refreshCache": "Refresh Cache",
"placeholderStartDate": "Start Date",
"placeholderEndDate": "End Date",
"valDictNameRequired": "Dict name cannot be empty",
"valDictTypeRequired": "Dict type cannot be empty",
"deleteTypeConfirm": "Are you sure to delete dict type \"{id}\"?",
"refreshSuccess": "Refreshed successfully"
}
},
"dict": {
@@ -431,5 +505,186 @@
"assign": "Assign",
"authorization": "Authorization",
"resetPassword": "Reset Password"
},
"registration": {
"outpatientRegistration": "Outpatient Registration",
"appointmentCheckIn": "Appointment Check-in",
"archive": "Archive",
"new": "New",
"query": "Query",
"electronicCertificate": "E-Certificate",
"idCard": "ID Card",
"medicalInsuranceCard": "Insurance Card",
"clear": "Clear",
"saveRegistration": "Save Registration",
"reprintRegistration": "Reprint Registration",
"patientIdentityInfo": "Patient Identity:",
"placeholderSearch": "Enter name/ID/card number",
"name": "Name",
"nameLabel": "Name:",
"gender": "Gender",
"genderLabel": "Gender:",
"age": "Age",
"ageLabel": "Age:",
"cardNo": "Card No.",
"cardNoLabel": "Card No.:",
"idCardNo": "ID No.",
"idCardNoLabel": "ID No.:",
"visitType": "Visit Type",
"visitTypeLabel": "Visit Type:",
"insuranceBalance": "Insurance Balance",
"insuranceBalanceLabel": "Insurance Balance:",
"insuranceType": "Insurance Type",
"insuranceTypeLabel": "Insurance Type:",
"insuranceName": "Insurance Name",
"insuranceNameLabel": "Insurance Name:",
"insuranceArea": "Insurance Area",
"insuranceAreaLabel": "Insurance Area:",
"overdraftLimit": "Overdraft Limit",
"overdraftLimitLabel": "Overdraft Limit:",
"feeNature": "Fee Nature",
"feeNatureLabel": "Fee Nature:",
"visitReason": "Visit Reason",
"visitReasonLabel": "Visit Reason:",
"phone": "Phone",
"phoneLabel": "Phone:",
"priority": "Priority",
"priorityLabel": "Priority:",
"visitDepartment": "Visit Department",
"visitDepartmentLabel": "Visit Department:",
"placeholderSelectDepartment": "Select department",
"registrationType": "Registration Type",
"doctor": "Doctor",
"doctorLabel": "Doctor:",
"specialDisease": "Special Disease",
"specialDiseaseLabel": "Special Disease:",
"registrationDepartment": "Reg. Department",
"registrationDepartmentLabel": "Reg. Department:",
"registrationFee": "Registration Fee",
"registrationFeeLabel": "Registration Fee:",
"consultationFee": "Consultation Fee",
"consultationFeeLabel": "Consultation Fee:",
"totalAmount": "Total Amount",
"totalAmountLabel": "Total Amount:",
"todayRegistered": "Today's Registrations",
"all": "All",
"normalRegistration": "Normal",
"returnRecord": "Returned",
"placeholderPatientName": "Enter patient name",
"startDate": "Start Date",
"endDate": "End Date",
"patientName": "Patient Name",
"patientGender": "Gender",
"contactPhone": "Phone",
"departmentName": "Department",
"registrationTypeCol": "*Reg. Type",
"expert": "Expert",
"feeNatureCol": "Fee Nature",
"registrationAmount": "Amount",
"cashier": "Cashier",
"visitStatus": "Visit Status",
"registrationDateTime": "Date/Time",
"action": "Action",
"returnRegistration": "Return",
"detail": "Detail",
"unknown": "Unknown",
"yuan": "",
"selectAppointmentPatient": "Select Appointment Patient",
"placeholderSearchAppointment": "Enter patient name to search",
"seqNo": "No.",
"idType": "ID Type",
"residentIdCard": "Resident ID Card",
"idNumber": "ID Number",
"mobileNumber": "Mobile",
"ticketType": "Ticket Type",
"expertTicket": "Expert",
"normalTicket": "Normal",
"appointmentAmount": "Amount",
"visitTime": "Visit Time",
"phoneFormatError": "Invalid phone number, please re-enter!",
"operationSuccess": "Operation successful",
"pleaseEnterQuery": "Please enter query content",
"readingCard": "Reading...",
"appointmentListFailed": "Failed to get appointment list",
"pleaseSelectPatient": "Please select a patient first",
"missingDepartmentInfo": "Missing department info, cannot check in. Contact admin.",
"missingPatientInfo": "Missing patient info, cannot check in. Contact admin.",
"checkInConfirm": "Check-in Confirmation",
"confirmCheckInMsg": "Confirm check-in for patient [{name}]?\nDept: {dept}\nDoctor: {doctor}\nFee: ¥{fee}",
"confirmCheckIn": "Confirm Check-in",
"processingCheckIn": "Processing check-in...",
"noRegistrationType": "No registration type configured for this department",
"noExactMatch": "No exact match for registration type, using default",
"patientIdMissing": "Patient ID missing, contact admin to check appointment data",
"preSettlementFailed": "Pre-settlement failed",
"checkInFailed": "Check-in failed: ",
"insuranceUpdateFailed": "Failed to update appointment status, please check in manually",
"registrationSuccess": "Outpatient Registration",
"valFeeNatureRequired": "Fee nature",
"valPatientIdRequired": "Patient cannot be empty",
"valPriorityRequired": "Priority cannot be empty",
"valDepartmentRequired": "Department cannot be empty",
"valRegTypeRequired": "Registration type cannot be empty",
"valDoctorRequired": "Doctor cannot be empty",
"valAccountTypeRequired": "Account type cannot be empty",
"valFeePricingRequired": "Fee pricing cannot be empty",
"valPhoneRequired": "Phone number cannot be empty",
"other": "Other"
},
"doctorstation": {
"currentPatients": "Current Patients",
"openCallQueue": "Click to open call queue",
"call": "Call",
"patientQueue": "Patient Queue",
"searchPatientPlaceholder": "Enter patient name",
"registrationTime": "Registration Time",
"medicalRecordNo": "Medical Record No.",
"unknown": "Unknown",
"patientInfo": "Patient Info",
"doctor": "Doctor",
"firstVisit": "First Visit",
"followUp": "Follow-up",
"finishVisit": "Finish",
"temporaryLeave": "Leave",
"cancelReception": "Cancel Reception",
"refund": "Refund",
"prescription": "Prescription",
"hospitalization": "Hospitalization",
"outpatientRecord": "Outpatient Record",
"diagnosis": "Diagnosis",
"medicalAdvice": "Orders",
"tcm": "TCM",
"inspection": "Lab Tests",
"examination": "Examinations",
"surgeryApplication": "Surgery",
"ePrescription": "E-Prescription",
"reportQuery": "Reports",
"consultation": "Consultation",
"today": "Today",
"yesterday": "Yesterday",
"withinThreeDays": "Last 3 Days",
"withinOneWeek": "Last Week",
"noPrescription": "No prescription available",
"selectPatientForRefund": "Please select a patient before refunding",
"operationSuccess": "Operation successful",
"selectPatientForCancel": "Please select a patient before cancelling reception",
"confirmCancelReception": "Are you sure to cancel reception? The patient will return to waiting status.",
"cancelReceptionSuccess": "Reception cancelled successfully",
"cancelReceptionFailed": "Failed to cancel reception",
"addDiagnosisFirst": "Please add diagnosis information first",
"selectDiagnosisType": "Please select diagnosis type",
"setMainDiagnosis": "Please set at least one primary diagnosis",
"getDiagnosisFailed": "Failed to get diagnosis information, please retry",
"selectPatient": "Please select a patient first",
"patientEncounterIncomplete": "Patient encounter information is incomplete, cannot proceed with hospitalization!",
"noDiagnosisConfirm": "This patient has no diagnosis. Would you like to add one?",
"goToAdd": "Go to Add",
"goToSet": "Go to Set",
"noMainDiagnosisConfirm": "This patient has no primary diagnosis. Would you like to set one?",
"checkHospitalizationFailed": "Failed to check hospitalization status!",
"alreadyHospitalized": "This patient is already hospitalized. Duplicate hospitalization is not allowed.",
"hospitalizationError": "An error occurred during hospitalization, please try again later!",
"infectiousReportSaved": "Infectious disease report saved successfully",
"defaultDepartment": "Cardiology"
}
}

View File

@@ -127,6 +127,35 @@
"yes": "Có",
"no": "Không"
},
"component": {
"rightToolbar": {
"hideSearch": "Ẩn Tìm Kiếm",
"showSearch": "Hiện Tìm Kiếm",
"refresh": "Làm Mới",
"showHideColumns": "Hiện/Ẩn Cột",
"showHide": "Hiện/Ẩn",
"show": "Hiện",
"hide": "Ẩn"
},
"upload": {
"selectFile": "Chọn Tệp",
"selectImage": "Chọn Ảnh",
"tipPrefix": "Vui lòng tải lên",
"tipSizeLimit": "kích thước không vượt quá",
"tipFormat": "định dạng",
"tipSuffix": "tệp",
"delete": "Xóa",
"preview": "Xem trước",
"fileFormatError": "Định dạng tệp không hợp lệ, vui lòng tải lên tệp định dạng {types}!",
"imageFormatError": "Định dạng tệp không hợp lệ, vui lòng tải lên ảnh định dạng {types}!",
"fileSizeError": "Kích thước tệp không được vượt quá {size} MB!",
"countError": "Số lượng tệp không được vượt quá {limit}!",
"uploadingFile": "Đang tải tệp, vui lòng đợi...",
"uploadingImage": "Đang tải ảnh, vui lòng đợi...",
"uploadFileFailed": "Tải tệp thất bại",
"uploadImageFailed": "Tải ảnh thất bại"
}
},
"system": {
"user": {
"userId": "ID Người Dùng",
@@ -279,7 +308,43 @@
"menuHidden": "Ẩn",
"menuChild": "Con",
"menuLayout": "Layout Ngoài",
"menuAlways": "Luôn Hiển Thị"
"menuAlways": "Luôn Hiển Thị",
"placeholderMenuName": "Nhập tên menu",
"expandCollapse": "Mở Rộng/Thu Gọn",
"fullPath": "Đường Dẫn Đầy Đủ",
"icon": "Biểu Tượng",
"isExternalLink": "Liên Kết Ngoài",
"isCache": "Bộ Nhớ Đệm",
"cacheYes": "Đệm",
"cacheNo": "Không Đệm",
"routeParam": "Tham Số Route",
"placeholderSelectParent": "Chọn menu cha",
"placeholderClickIcon": "Nhấn để chọn biểu tượng",
"placeholderRoutePath": "Nhập đường dẫn route",
"placeholderComponent": "Nhập đường dẫn component",
"placeholderPermi": "Nhập mã quyền",
"placeholderRouteParam": "Nhập tham số route",
"tooltipExternalLink": "Nếu là liên kết ngoài, đường dẫn phải bắt đầu bằng `http(s)://`",
"tooltipRoutePath": "Đường dẫn route, ví dụ: `user`, URL ngoài phải bắt đầu bằng `http(s)://`",
"tooltipComponent": "Đường dẫn component, ví dụ: `system/user/index`, mặc định trong thư mục `views`",
"tooltipPermi": "Mã quyền được định nghĩa trong controller, ví dụ: @PreAuthorize(`@ss.hasPermi('system:user:list')`)",
"tooltipRouteParam": "Tham số route mặc định, ví dụ: `{id: 1, name: ry}`",
"tooltipCache": "Nếu bật đệm, `name` component phải khớp với đường dẫn route",
"tooltipVisible": "Nếu ẩn, route sẽ không hiển thị trên thanh bên nhưng vẫn có thể truy cập",
"tooltipMenuStatus": "Nếu vô hiệu hóa, route sẽ không hiển thị trên thanh bên và không thể truy cập",
"addMenu": "Thêm Menu",
"editMenu": "Sửa Menu",
"rootCategory": "Danh Mục Gốc",
"valMenuNameRequired": "Tên menu không được để trống",
"valOrderNumRequired": "Thứ tự menu không được để trống",
"valPathRequired": "Đường dẫn route không được để trống",
"routePathExists": "Đường dẫn route đã tồn tại",
"cacheRefreshed": "Đã làm mới bộ nhớ đệm menu, danh sách đã cập nhật",
"cacheRefreshFailed": "Làm mới bộ nhớ đệm menu thất bại",
"deleteConfirm": "Bạn có chắc chắn muốn xóa menu \"{name}\"?",
"noModuleAvailable": "{name} chưa có module tương ứng",
"moduleAccessFailed": "Module {name} không thể truy cập, vui lòng kiểm tra quyền hoặc liên hệ quản trị",
"moduleNavigateFailed": "Điều hướng module {name} thất bại"
},
"dict": {
"dictCode": "Mã Từ Điển",
@@ -318,7 +383,16 @@
"valDictLabelRequired": "Nhãn dữ liệu không được để trống",
"valDictValueRequired": "Giá trị dữ liệu không được để trống",
"valDictSortRequired": "Thứ tự không được để trống",
"deleteConfirm": "Bạn có chắc chắn muốn xóa dữ liệu từ điển \"{id}\"?"
"deleteConfirm": "Bạn có chắc chắn muốn xóa dữ liệu từ điển \"{id}\"?",
"placeholderDictName": "Nhập tên từ điển",
"placeholderDictType": "Nhập loại từ điển",
"refreshCache": "Làm Mới Bộ Nhớ Đệm",
"placeholderStartDate": "Ngày bắt đầu",
"placeholderEndDate": "Ngày kết thúc",
"valDictNameRequired": "Tên từ điển không được để trống",
"valDictTypeRequired": "Loại từ điển không được để trống",
"deleteTypeConfirm": "Bạn có chắc chắn muốn xóa loại từ điển \"{id}\"?",
"refreshSuccess": "Làm mới thành công"
}
},
"dict": {
@@ -431,5 +505,186 @@
"assign": "Phân Bổ",
"authorization": "Ủy Quyền",
"resetPassword": "Đặt Lại Mật Khẩu"
},
"registration": {
"outpatientRegistration": "Đăng Ký Khám Bệnh",
"appointmentCheckIn": "Check-in Lịch Hẹn",
"archive": "Hồ Sơ",
"new": "Tạo Mới",
"query": "Tìm Kiếm",
"electronicCertificate": "Chứng Từ Điện Tử",
"idCard": "CCCD",
"medicalInsuranceCard": "Thẻ BHYT",
"clear": "Xóa",
"saveRegistration": "Lưu Đăng Ký",
"reprintRegistration": "In Lại Đăng Ký",
"patientIdentityInfo": "Thông Tin Bệnh Nhân:",
"placeholderSearch": "Nhập tên/CCCD/số thẻ",
"name": "Họ Tên",
"nameLabel": "Họ Tên:",
"gender": "Giới Tính",
"genderLabel": "Giới Tính:",
"age": "Tuổi",
"ageLabel": "Tuổi:",
"cardNo": "Số Thẻ",
"cardNoLabel": "Số Thẻ:",
"idCardNo": "Số CCCD",
"idCardNoLabel": "Số CCCD:",
"visitType": "Loại Khám",
"visitTypeLabel": "Loại Khám:",
"insuranceBalance": "Số Dư BHYT",
"insuranceBalanceLabel": "Số Dư BHYT:",
"insuranceType": "Loại BHYT",
"insuranceTypeLabel": "Loại BHYT:",
"insuranceName": "Tên BHYT",
"insuranceNameLabel": "Tên BHYT:",
"insuranceArea": "Khu Vực BHYT",
"insuranceAreaLabel": "Khu Vực BHYT:",
"overdraftLimit": "Hạn Mức Nợ",
"overdraftLimitLabel": "Hạn Mức Nợ:",
"feeNature": "Loại Phí",
"feeNatureLabel": "Loại Phí:",
"visitReason": "Lý Do Khám",
"visitReasonLabel": "Lý Do Khám:",
"phone": "Điện Thoại",
"phoneLabel": "Điện Thoại:",
"priority": "Ưu Tiên",
"priorityLabel": "Ưu Tiên:",
"visitDepartment": "Khoa Khám",
"visitDepartmentLabel": "Khoa Khám:",
"placeholderSelectDepartment": "Chọn khoa khám",
"registrationType": "Loại Đăng Ký",
"doctor": "Bác Sĩ",
"doctorLabel": "Bác Sĩ:",
"specialDisease": "Bệnh Đặc Biệt",
"specialDiseaseLabel": "Bệnh Đặc Biệt:",
"registrationDepartment": "Khoa Đăng Ký",
"registrationDepartmentLabel": "Khoa Đăng Ký:",
"registrationFee": "Phí Đăng Ký",
"registrationFeeLabel": "Phí Đăng Ký:",
"consultationFee": "Phí Khám",
"consultationFeeLabel": "Phí Khám:",
"totalAmount": "Tổng Tiền",
"totalAmountLabel": "Tổng Tiền:",
"todayRegistered": "Đã Đăng Ký Hôm Nay",
"all": "Tất Cả",
"normalRegistration": "Bình Thường",
"returnRecord": "Đã Hủy",
"placeholderPatientName": "Nhập tên bệnh nhân",
"startDate": "Ngày Bắt Đầu",
"endDate": "Ngày Kết Thúc",
"patientName": "Tên Bệnh Nhân",
"patientGender": "Giới Tính",
"contactPhone": "Điện Thoại",
"departmentName": "Khoa",
"registrationTypeCol": "*Loại ĐK",
"expert": "Chuyên Gia",
"feeNatureCol": "Loại Phí",
"registrationAmount": "Số Tiền",
"cashier": "Thu Ngân",
"visitStatus": "Trạng Thái",
"registrationDateTime": "Ngày/Giờ",
"action": "Thao Tác",
"returnRegistration": "Hủy",
"detail": "Chi Tiết",
"unknown": "Không Rõ",
"yuan": "",
"selectAppointmentPatient": "Chọn Bệnh Nhân Lịch Hẹn",
"placeholderSearchAppointment": "Nhập tên bệnh nhân để tìm",
"seqNo": "STT",
"idType": "Loại Giấy Tờ",
"residentIdCard": "CCCD",
"idNumber": "Số Giấy Tờ",
"mobileNumber": "Số ĐT",
"ticketType": "Loại Vé",
"expertTicket": "Chuyên Gia",
"normalTicket": "Bình Thường",
"appointmentAmount": "Số Tiền",
"visitTime": "Thời Gian Khám",
"phoneFormatError": "Số điện thoại không hợp lệ, vui lòng nhập lại!",
"operationSuccess": "Thao tác thành công",
"pleaseEnterQuery": "Vui lòng nhập nội dung tìm kiếm",
"readingCard": "Đang đọc...",
"appointmentListFailed": "Lấy danh sách lịch hẹn thất bại",
"pleaseSelectPatient": "Vui lòng chọn bệnh nhân trước",
"missingDepartmentInfo": "Thiếu thông tin khoa, không thể check-in. Liên hệ quản trị.",
"missingPatientInfo": "Thiếu thông tin bệnh nhân, không thể check-in. Liên hệ quản trị.",
"checkInConfirm": "Xác Nhận Check-in",
"confirmCheckInMsg": "Xác nhận check-in cho bệnh nhân [{name}]?\nKhoa: {dept}\nBác sĩ: {doctor}\nPhí: ¥{fee}",
"confirmCheckIn": "Xác Nhận Check-in",
"processingCheckIn": "Đang xử lý check-in...",
"noRegistrationType": "Khoa chưa cấu hình loại đăng ký",
"noExactMatch": "Không khớp chính xác loại đăng ký, sử dụng mặc định",
"patientIdMissing": "Thiếu ID bệnh nhân, liên hệ quản trị kiểm tra dữ liệu lịch hẹn",
"preSettlementFailed": "Thanh toán trước thất bại",
"checkInFailed": "Check-in thất bại: ",
"insuranceUpdateFailed": "Cập nhật trạng thái lịch hẹn thất bại, vui lòng check-in thủ công",
"registrationSuccess": "Đăng Ký Khám Bệnh",
"valFeeNatureRequired": "Loại phí",
"valPatientIdRequired": "Bệnh nhân không được để trống",
"valPriorityRequired": "Ưu tiên không được để trống",
"valDepartmentRequired": "Khoa khám không được để trống",
"valRegTypeRequired": "Loại đăng ký không được để trống",
"valDoctorRequired": "Bác sĩ không được để trống",
"valAccountTypeRequired": "Loại tài khoản không được để trống",
"valFeePricingRequired": "Định giá phí không được để trống",
"valPhoneRequired": "Số điện thoại không được để trống",
"other": "Khác"
},
"doctorstation": {
"currentPatients": "Bệnh Nhân Hiện Tại",
"openCallQueue": "Nhấn để mở giao diện gọi số",
"call": "Gọi",
"patientQueue": "Hàng Chờ Bệnh Nhân",
"searchPatientPlaceholder": "Nhập tên bệnh nhân",
"registrationTime": "Thời Gian Đăng Ký",
"medicalRecordNo": "Số Bệnh Án",
"unknown": "Không rõ",
"patientInfo": "Thông Tin Bệnh Nhân",
"doctor": "Bác Sĩ",
"firstVisit": "Khám Lần Đầu",
"followUp": "Tái Khám",
"finishVisit": "Hoàn Thành",
"temporaryLeave": "Tạm Rời",
"cancelReception": "Hủy Tiếp Đón",
"refund": "Hoàn Phí",
"prescription": "Đơn Thuốc",
"hospitalization": "Nhập Viện",
"outpatientRecord": "Bệnh Án Ngoại Trú",
"diagnosis": "Chẩn Đoán",
"medicalAdvice": "Y Lệnh",
"tcm": "Y Học Cổ Truyền",
"inspection": "Xét Nghiệm",
"examination": "Khám",
"surgeryApplication": "Đăng Ký Phẫu Thuật",
"ePrescription": "Đơn Thuốc Điện Tử",
"reportQuery": "Tra Cứu Kết Quả",
"consultation": "Hội Chẩn",
"today": "Hôm nay",
"yesterday": "Hôm qua",
"withinThreeDays": "3 ngày qua",
"withinOneWeek": "Tuần qua",
"noPrescription": "Chưa có đơn thuốc",
"selectPatientForRefund": "Vui lòng chọn bệnh nhân trước khi hoàn phí",
"operationSuccess": "Thao tác thành công",
"selectPatientForCancel": "Vui lòng chọn bệnh nhân trước khi hủy tiếp đón",
"confirmCancelReception": "Bạn có chắc muốn hủy tiếp đón? Bệnh nhân sẽ quay lại trạng thái chờ.",
"cancelReceptionSuccess": "Hủy tiếp đón thành công",
"cancelReceptionFailed": "Hủy tiếp đón thất bại",
"addDiagnosisFirst": "Vui lòng thêm thông tin chẩn đoán trước",
"selectDiagnosisType": "Vui lòng chọn loại chẩn đoán",
"setMainDiagnosis": "Vui lòng đặt ít nhất một chẩn đoán chính",
"getDiagnosisFailed": "Lấy thông tin chẩn đoán thất bại, vui lòng thử lại",
"selectPatient": "Vui lòng chọn bệnh nhân trước",
"patientEncounterIncomplete": "Thông tin khám bệnh không đầy đủ, không thể nhập viện!",
"noDiagnosisConfirm": "Bệnh nhân chưa có chẩn đoán. Bạn có muốn thêm không?",
"goToAdd": "Đi thêm",
"goToSet": "Đi đặt",
"noMainDiagnosisConfirm": "Bệnh nhân chưa có chẩn đoán chính. Bạn có muốn đặt không?",
"checkHospitalizationFailed": "Kiểm tra trạng thái nhập viện thất bại!",
"alreadyHospitalized": "Bệnh nhân đã nhập viện, không cho phép nhập viện lại",
"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"
}
}

View File

@@ -127,6 +127,35 @@
"yes": "是",
"no": "否"
},
"component": {
"rightToolbar": {
"hideSearch": "隐藏搜索",
"showSearch": "显示搜索",
"refresh": "刷新",
"showHideColumns": "显隐列",
"showHide": "显示/隐藏",
"show": "显示",
"hide": "隐藏"
},
"upload": {
"selectFile": "选取文件",
"selectImage": "选择图片",
"tipPrefix": "请上传",
"tipSizeLimit": "大小不超过",
"tipFormat": "格式为",
"tipSuffix": "的文件",
"delete": "删除",
"preview": "预览",
"fileFormatError": "文件格式不正确, 请上传{types}格式文件!",
"imageFormatError": "文件格式不正确, 请上传{types}图片格式文件!",
"fileSizeError": "上传文件大小不能超过 {size} MB!",
"countError": "上传文件数量不能超过 {limit} 个!",
"uploadingFile": "正在上传文件,请稍候...",
"uploadingImage": "正在上传图片,请稍候...",
"uploadFileFailed": "上传文件失败",
"uploadImageFailed": "上传图片失败"
}
},
"system": {
"user": {
"userId": "用户ID",
@@ -278,7 +307,43 @@
"menuHidden": "隐藏状态",
"menuChild": "子菜单",
"menuLayout": "外层菜单",
"menuAlways": "始终显示"
"menuAlways": "始终显示",
"placeholderMenuName": "请输入菜单名称",
"expandCollapse": "展开/折叠",
"fullPath": "完整路径",
"icon": "图标",
"isExternalLink": "是否外链",
"isCache": "是否缓存",
"cacheYes": "缓存",
"cacheNo": "不缓存",
"routeParam": "路由参数",
"placeholderSelectParent": "选择上级菜单",
"placeholderClickIcon": "点击选择图标",
"placeholderRoutePath": "请输入路由地址",
"placeholderComponent": "请输入组件路径",
"placeholderPermi": "请输入权限标识",
"placeholderRouteParam": "请输入路由参数",
"tooltipExternalLink": "选择是外链则路由地址需要以`http(s)://`开头",
"tooltipRoutePath": "访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头",
"tooltipComponent": "访问的组件路径,如:`system/user/index`,默认在`views`目录下",
"tooltipPermi": "控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)",
"tooltipRouteParam": "访问路由的默认传递参数,如:`{id: 1, name: ry}`",
"tooltipCache": "选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致",
"tooltipVisible": "选择隐藏则路由将不会出现在侧边栏,但仍然可以访问",
"tooltipMenuStatus": "选择停用则路由将不会出现在侧边栏,也不能被访问",
"addMenu": "添加菜单",
"editMenu": "修改菜单",
"rootCategory": "主类目",
"valMenuNameRequired": "菜单名称不能为空",
"valOrderNumRequired": "菜单顺序不能为空",
"valPathRequired": "路由地址不能为空",
"routePathExists": "路由地址已存在",
"cacheRefreshed": "菜单缓存已刷新,列表已更新",
"cacheRefreshFailed": "刷新菜单缓存失败",
"deleteConfirm": "是否确认删除名称为\"{name}\"的数据项?",
"noModuleAvailable": "{name} 暂无对应的功能模块",
"moduleAccessFailed": "{name} 模块暂无法访问,请检查权限或联系管理员",
"moduleNavigateFailed": "{name} 模块跳转失败"
},
"dict": {
"dictCode": "字典编码",
@@ -317,7 +382,16 @@
"valDictLabelRequired": "数据标签不能为空",
"valDictValueRequired": "数据键值不能为空",
"valDictSortRequired": "数据顺序不能为空",
"deleteConfirm": "是否确认删除字典编码为\"{id}\"的数据项?"
"deleteConfirm": "是否确认删除字典编码为\"{id}\"的数据项?",
"placeholderDictName": "请输入字典名称",
"placeholderDictType": "请输入字典类型",
"refreshCache": "刷新缓存",
"placeholderStartDate": "开始日期",
"placeholderEndDate": "结束日期",
"valDictNameRequired": "字典名称不能为空",
"valDictTypeRequired": "字典类型不能为空",
"deleteTypeConfirm": "是否确认删除字典编号为\"{id}\"的数据项?",
"refreshSuccess": "刷新成功"
}
},
"dict": {
@@ -430,5 +504,186 @@
"assign": "分配",
"authorization": "授权",
"resetPassword": "重置密码"
},
"registration": {
"outpatientRegistration": "门诊挂号",
"appointmentCheckIn": "预约签到",
"archive": "档案",
"new": "新建",
"query": "查询",
"electronicCertificate": "电子凭证",
"idCard": "身份证",
"medicalInsuranceCard": "医保卡",
"clear": "清空",
"saveRegistration": "保存挂号",
"reprintRegistration": "补打挂号",
"patientIdentityInfo": "患者身份信息:",
"placeholderSearch": "请输入姓名/身份证/就诊卡号",
"name": "姓名",
"nameLabel": "姓名:",
"gender": "性别",
"genderLabel": "性别:",
"age": "年龄",
"ageLabel": "年龄:",
"cardNo": "就诊卡号",
"cardNoLabel": "就诊卡号:",
"idCardNo": "证件号",
"idCardNoLabel": "证件号:",
"visitType": "初复诊",
"visitTypeLabel": "初复诊:",
"insuranceBalance": "医保余额",
"insuranceBalanceLabel": "医保余额:",
"insuranceType": "参保类型",
"insuranceTypeLabel": "参保类型:",
"insuranceName": "医保名称",
"insuranceNameLabel": "医保名称:",
"insuranceArea": "医保区域",
"insuranceAreaLabel": "医保区域:",
"overdraftLimit": "欠费限制额度",
"overdraftLimitLabel": "欠费限制额度:",
"feeNature": "费用性质",
"feeNatureLabel": "费用性质:",
"visitReason": "就诊原因",
"visitReasonLabel": "就诊原因:",
"phone": "电话",
"phoneLabel": "电话:",
"priority": "优先级",
"priorityLabel": "优先级:",
"visitDepartment": "就诊科室",
"visitDepartmentLabel": "就诊科室:",
"placeholderSelectDepartment": "请选择就诊科室",
"registrationType": "挂号类型",
"doctor": "医生",
"doctorLabel": "医生:",
"specialDisease": "特病病种",
"specialDiseaseLabel": "特病病种:",
"registrationDepartment": "挂号科室",
"registrationDepartmentLabel": "挂号科室:",
"registrationFee": "挂号费",
"registrationFeeLabel": "挂号费:",
"consultationFee": "诊疗费",
"consultationFeeLabel": "诊疗费:",
"totalAmount": "总金额",
"totalAmountLabel": "总金额:",
"todayRegistered": "当日已挂号",
"all": "全部",
"normalRegistration": "正常挂号",
"returnRecord": "退号记录",
"placeholderPatientName": "请输入患者姓名",
"startDate": "开始日期",
"endDate": "结束日期",
"patientName": "患者姓名",
"patientGender": "患者性别",
"contactPhone": "联系电话",
"departmentName": "科室名称",
"registrationTypeCol": "*挂号类型",
"expert": "专家",
"feeNatureCol": "费用性质",
"registrationAmount": "挂号金额",
"cashier": "收款人",
"visitStatus": "就诊状态",
"registrationDateTime": "挂号日期/时间",
"action": "操作",
"returnRegistration": "退号",
"detail": "详情",
"unknown": "未知",
"yuan": "元",
"selectAppointmentPatient": "请选择预约的患者",
"placeholderSearchAppointment": "输入患者姓名回车查询",
"seqNo": "序号",
"idType": "证件类型",
"residentIdCard": "居民身份证",
"idNumber": "证件号码",
"mobileNumber": "手机号码",
"ticketType": "号源类型",
"expertTicket": "专家号",
"normalTicket": "普通号",
"appointmentAmount": "预约金额",
"visitTime": "就诊时间",
"phoneFormatError": "手机号格式不正确,请重新输入!",
"operationSuccess": "操作成功",
"pleaseEnterQuery": "请输入查询内容",
"readingCard": "正在读取...",
"appointmentListFailed": "获取预约列表失败",
"pleaseSelectPatient": "请先选择患者",
"missingDepartmentInfo": "该号源缺少科室信息,无法完成签到,请联系管理员",
"missingPatientInfo": "该号源缺少患者信息,无法完成签到,请联系管理员",
"checkInConfirm": "签到确认",
"confirmCheckInMsg": "确认为患者【{name}】办理签到挂号?\n科室{dept}\n医生{doctor}\n费用¥{fee}",
"confirmCheckIn": "确认签到",
"processingCheckIn": "正在处理签到挂号...",
"noRegistrationType": "该科室未配置挂号类型,无法自动签到",
"noExactMatch": "未精确匹配到挂号类型,已使用默认类型",
"patientIdMissing": "患者ID缺失请联系管理员检查预约数据",
"preSettlementFailed": "预结算失败",
"checkInFailed": "签到处理失败: ",
"insuranceUpdateFailed": "预约状态更新失败,请手动签到",
"registrationSuccess": "门诊挂号单",
"valFeeNatureRequired": "费用性质",
"valPatientIdRequired": "病人不能为空",
"valPriorityRequired": "优先级不能为空",
"valDepartmentRequired": "就诊科室不能为空",
"valRegTypeRequired": "挂号类型不能为空",
"valDoctorRequired": "医生不能为空",
"valAccountTypeRequired": "账户类型不能为空",
"valFeePricingRequired": "费用定价不能为空",
"valPhoneRequired": "联系电话不能为空",
"other": "其他"
},
"doctorstation": {
"currentPatients": "现诊患者",
"openCallQueue": "点击打开叫号界面",
"call": "呼叫",
"patientQueue": "患者队列",
"searchPatientPlaceholder": "请输入患者名",
"registrationTime": "挂号时间",
"medicalRecordNo": "病历号",
"unknown": "未知",
"patientInfo": "患者信息",
"doctor": "医生",
"firstVisit": "初诊",
"followUp": "复诊",
"finishVisit": "完诊",
"temporaryLeave": "暂离",
"cancelReception": "取消接诊",
"refund": "退费",
"prescription": "处方单",
"hospitalization": "办理住院",
"outpatientRecord": "门诊病历",
"diagnosis": "诊断",
"medicalAdvice": "医嘱",
"tcm": "中医",
"inspection": "检验",
"examination": "检查",
"surgeryApplication": "手术申请",
"ePrescription": "电子处方",
"reportQuery": "报告查询",
"consultation": "会诊",
"today": "今天",
"yesterday": "昨天",
"withinThreeDays": "三天内",
"withinOneWeek": "一周内",
"noPrescription": "暂无处方单",
"selectPatientForRefund": "请先选择患者后再进行退费操作",
"operationSuccess": "操作成功",
"selectPatientForCancel": "请先选择患者后再进行取消接诊操作",
"confirmCancelReception": "确定要取消接诊该患者吗?取消后患者将回到待诊状态。",
"cancelReceptionSuccess": "取消接诊成功",
"cancelReceptionFailed": "取消接诊失败",
"addDiagnosisFirst": "请先添加诊断信息",
"selectDiagnosisType": "请选择诊断类型",
"setMainDiagnosis": "请至少设置一条主诊断",
"getDiagnosisFailed": "获取诊断信息失败,请重试",
"selectPatient": "请先选择患者",
"patientEncounterIncomplete": "患者就诊信息不完整,无法办理住院!",
"noDiagnosisConfirm": "该患者暂无诊断信息,是否前往添加诊断?",
"goToAdd": "前往添加",
"goToSet": "前往设置",
"noMainDiagnosisConfirm": "该患者暂无主诊断信息,是否前往设置主诊断?",
"checkHospitalizationFailed": "检查住院状态失败!",
"alreadyHospitalized": "该患者,已办理入院,不允许重复办理",
"hospitalizationError": "办理住院过程中发生错误,请稍后重试!",
"infectiousReportSaved": "传染病报告卡保存成功",
"defaultDepartment": "心内科"
}
}

View File

@@ -12,7 +12,7 @@
<el-card>
<template #header>
<div style="display: flex; align-items: center; width: 100%">
<span style="font-size: 16px; font-weight: bold; margin-right: 20px;">门诊挂号</span>
<span style="font-size: 16px; font-weight: bold; margin-right: 20px;">{{ $t('registration.outpatientRegistration') }}</span>
<div style="flex: 1; display: flex; justify-content: center; align-items: center;">
<el-button
type="success"
@@ -20,7 +20,7 @@
size="small"
@click="handleCheckIn"
>
预约签到
{{ $t('registration.appointmentCheckIn') }}
</el-button>
<el-button
type="primary"
@@ -28,7 +28,7 @@
size="small"
@click="goToPatientRecord"
>
档案
{{ $t('registration.archive') }}
</el-button>
<el-button
type="primary"
@@ -36,7 +36,7 @@
size="small"
@click="handleAddPatient"
>
新建
{{ $t('registration.new') }}
</el-button>
<el-button
type="primary"
@@ -45,7 +45,7 @@
size="small"
@click="handleSearch"
>
查询
{{ $t('registration.query') }}
</el-button>
<el-button
type="primary"
@@ -53,7 +53,7 @@
size="small"
@click="handleReadCard('01')"
>
电子凭证
{{ $t('registration.electronicCertificate') }}
</el-button>
<el-button
type="primary"
@@ -62,7 +62,7 @@
:disabled="true"
@click="handleReadCard('02')"
>
身份证
{{ $t('registration.idCard') }}
</el-button>
<el-button
type="primary"
@@ -70,7 +70,7 @@
size="small"
@click="handleReadCard('03')"
>
医保卡
{{ $t('registration.medicalInsuranceCard') }}
</el-button>
<el-button
type="warning"
@@ -79,7 +79,7 @@
size="small"
@click="handleClear"
>
清空
{{ $t('registration.clear') }}
</el-button>
<el-button
type="primary"
@@ -87,7 +87,7 @@
size="small"
@click="handleAdd"
>
保存挂号
{{ $t('registration.saveRegistration') }}
</el-button>
<el-button
type="info"
@@ -95,7 +95,7 @@
size="small"
@click="handleReprint"
>
补打挂号
{{ $t('registration.reprintRegistration') }}
</el-button>
</div>
</div>
@@ -109,7 +109,7 @@
<el-row :gutter="24">
<el-col :span="5">
<el-form-item
label="患者身份信息:"
:label="$t('registration.patientIdentityInfo')"
prop="searchKey"
>
<el-popover
@@ -127,7 +127,7 @@
<template #reference>
<el-input
v-model="form.searchKey"
placeholder="请输入姓名/身份证/就诊卡号"
:placeholder="$t('registration.placeholderSearch')"
@focus="handleFocus"
@blur="handleBlur"
@input="handleSearchPatient"
@@ -138,19 +138,19 @@
</el-col>
<el-col :span="5">
<el-form-item
label="姓名:"
:label="$t('registration.nameLabel')"
prop="name"
>
<el-input
v-model="form.name"
placeholder="姓名"
:placeholder="$t('registration.name')"
:disabled="true"
/>
</el-form-item>
</el-col>
<el-col :span="4">
<el-form-item
label="性别:"
:label="$t('registration.genderLabel')"
prop="genderEnum_enumText"
class="custom-label-spacing"
>
@@ -163,7 +163,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="年龄:"
:label="$t('registration.ageLabel')"
prop="age"
class="custom-label-spacing"
>
@@ -178,7 +178,7 @@
<el-row :gutter="24">
<el-col :span="5">
<el-form-item
label="就诊卡号:"
:label="$t('registration.cardNoLabel')"
prop="card"
>
<el-input
@@ -190,7 +190,7 @@
</el-col>
<el-col :span="6">
<el-form-item
label="证件号:"
:label="$t('registration.idCardNoLabel')"
prop="idCard"
>
<el-input
@@ -202,7 +202,7 @@
</el-col>
<el-col :span="5">
<el-form-item
label="初复诊:"
:label="$t('registration.visitTypeLabel')"
prop="firstEnum_enumText"
class="custom-label-spacing"
>
@@ -215,7 +215,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="医保余额:"
:label="$t('registration.insuranceBalanceLabel')"
prop="balanceAmount"
class="custom-label-spacing"
>
@@ -228,7 +228,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="参保类型:"
:label="$t('registration.insuranceTypeLabel')"
prop="cb"
class="custom-label-spacing"
>
@@ -243,7 +243,7 @@
<el-row :gutter="24">
<el-col :span="5">
<el-form-item
label="医保名称:"
:label="$t('registration.insuranceNameLabel')"
prop="ybName"
class="custom-label-spacing"
>
@@ -256,12 +256,12 @@
</el-col>
<el-col :span="6">
<el-form-item
label="医保区域:"
:label="$t('registration.insuranceAreaLabel')"
prop="ybAreaNo"
>
<el-select
v-model="form.ybAreaNo"
placeholder="医保区域"
:placeholder="$t('registration.insuranceArea')"
clearable
style="width: 240px"
:disabled="true"
@@ -277,7 +277,7 @@
</el-col>
<el-col :span="5">
<el-form-item
label="欠费限制额度:"
:label="$t('registration.overdraftLimitLabel')"
prop="limitAccount"
class="custom-label-spacing"
>
@@ -292,14 +292,14 @@
<el-row :gutter="24">
<el-col :span="5">
<el-form-item
label="费用性质:"
:label="$t('registration.feeNatureLabel')"
prop="contractNo"
class="custom-label-spacing"
>
<el-select
ref="contractNameRef"
v-model="form.contractNo"
placeholder="费用性质"
:placeholder="$t('registration.feeNature')"
clearable
style="width: 240px"
>
@@ -314,13 +314,13 @@
</el-col>
<el-col :span="6">
<el-form-item
label="就诊原因:"
:label="$t('registration.visitReasonLabel')"
prop="jzyy"
>
<el-select
ref="jzyyRef"
v-model="form.jzyy"
placeholder="就诊原因"
:placeholder="$t('registration.visitReason')"
clearable
style="width: 240px"
>
@@ -335,7 +335,7 @@
</el-col>
<el-col :span="5">
<el-form-item
label="电话:"
:label="$t('registration.phoneLabel')"
prop="phone"
class="custom-label-spacing"
>
@@ -348,14 +348,14 @@
</el-col>
<el-col :span="4">
<el-form-item
label="优先级:"
:label="$t('registration.priorityLabel')"
prop="priorityEnum"
class="custom-label-spacing"
>
<el-select
ref="prioritySelectRef"
v-model="form.priorityEnum"
placeholder="优先级"
:placeholder="$t('registration.priority')"
clearable
style="width: 240px"
>
@@ -401,7 +401,7 @@
</el-col> -->
<el-col :span="5">
<el-form-item
label="就诊科室:"
:label="$t('registration.visitDepartmentLabel')"
prop="orgId"
class="custom-label-spacing"
>
@@ -415,7 +415,7 @@
children: 'children',
}"
value-key="id"
placeholder="请选择就诊科室"
:placeholder="$t('registration.placeholderSelectDepartment')"
check-strictly
:expand-on-click-node="false"
:filter-node-method="filterNode"
@@ -435,14 +435,14 @@
</el-col>
<el-col :span="6">
<el-form-item
label="挂号类型"
:label="$t('registration.registrationType')"
prop="serviceTypeId"
class="custom-label-spacing"
>
<el-select
ref="serviceTypeRef"
v-model="form.serviceTypeId"
placeholder="挂号类型"
:placeholder="$t('registration.registrationType')"
clearable
style="width: 240px"
@change="handleServiceTypeChange"
@@ -458,13 +458,13 @@
</el-col>
<el-col :span="5">
<el-form-item
label="医生:"
:label="$t('registration.doctorLabel')"
prop="practitionerId"
>
<el-select
ref="doctorRef"
v-model="form.practitionerId"
placeholder="医生"
:placeholder="$t('registration.doctor')"
clearable
style="width: 240px"
@change="setInfo"
@@ -480,14 +480,14 @@
</el-col>
<el-col :span="5">
<el-form-item
label="特病病种:"
:label="$t('registration.specialDiseaseLabel')"
prop="pyStr"
class="custom-label-spacing"
>
<el-select
ref="ybTypeRef"
v-model="form.ybType"
placeholder="特病病种"
:placeholder="$t('registration.specialDisease')"
clearable
style="width: 240px"
disabled
@@ -505,7 +505,7 @@
<el-row :gutter="24">
<el-col :span="4">
<el-form-item
label="挂号科室:"
:label="$t('registration.registrationDepartmentLabel')"
prop="locationId_dictText"
>
<el-input
@@ -517,7 +517,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="医生:"
:label="$t('registration.doctorLabel')"
prop="doctorName"
>
<el-input
@@ -529,7 +529,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="挂号费:"
:label="$t('registration.registrationFeeLabel')"
prop="price"
class="custom-label-spacing"
>
@@ -542,7 +542,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="诊疗费:"
:label="$t('registration.consultationFeeLabel')"
prop="activityPrice"
class="custom-label-spacing"
>
@@ -555,7 +555,7 @@
</el-col>
<el-col :span="4">
<el-form-item
label="总金额:"
:label="$t('registration.totalAmountLabel')"
prop="totalPrice"
class="custom-label-spacing"
>
@@ -590,20 +590,20 @@
<el-card>
<template #header>
<div style="display: flex; align-items: center; justify-content: space-between;">
<span style="vertical-align: middle">当日已挂号</span>
<span style="vertical-align: middle">{{ $t('registration.todayRegistered') }}</span>
<el-radio-group
v-model="queryType"
size="small"
@change="handleQueryTypeChange"
>
<el-radio-button value="all">
全部
{{ $t('registration.all') }}
</el-radio-button>
<el-radio-button value="normal">
正常挂号
{{ $t('registration.normalRegistration') }}
</el-radio-button>
<el-radio-button value="returned">
退号记录
{{ $t('registration.returnRecord') }}
</el-radio-button>
</el-radio-group>
</div>
@@ -611,7 +611,7 @@
<el-input
v-model="queryParams.searchKey"
style="width: 200px; margin-bottom: 10px"
placeholder="请输入患者姓名"
:placeholder="$t('registration.placeholderPatientName')"
@keyup.enter="handleQuery"
>
<template #append>
@@ -624,8 +624,8 @@
<el-date-picker
v-model="dateRange"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:start-placeholder="$t('registration.startDate')"
:end-placeholder="$t('registration.endDate')"
style="width: 300px; margin-bottom: 10px; margin-left: 20px"
value-format="YYYY-MM-DD"
:clearable="false"
@@ -669,14 +669,14 @@
</vxe-column>
<vxe-column
key="patientName"
title="患者姓名"
:title="$t('registration.patientName')"
align="center"
field="patientName"
:min-width="100"
/>
<vxe-column
key="age"
title="年龄"
:title="$t('registration.age')"
align="center"
field="age"
:min-width="60"
@@ -687,21 +687,21 @@
</vxe-column>
<vxe-column
key="genderEnum_enumText"
title="患者性别"
:title="$t('registration.patientGender')"
align="center"
field="genderEnum_enumText"
:min-width="100"
/>
<vxe-column
key="phone"
title="联系电话"
:title="$t('registration.contactPhone')"
align="center"
field="phone"
:min-width="120"
/>
<vxe-column
key="identifierNo"
title="就诊卡号"
:title="$t('registration.cardNo')"
align="center"
:min-width="150"
>
@@ -711,7 +711,7 @@
</vxe-column>
<vxe-column
key="organizationName"
title="科室名称"
:title="$t('registration.departmentName')"
align="center"
field="organizationName"
show-overflow="title"
@@ -719,7 +719,7 @@
/>
<vxe-column
key="healthcareName"
title="*挂号类型 "
:title="$t('registration.registrationTypeCol') + ' '"
align="center"
field="healthcareName"
show-overflow="title"
@@ -727,7 +727,7 @@
>
<template #default="scope">
<span>
{{ (scope.row.healthcareName || '').replace('挂号', '') }}{{ scope.row.isFromAppointment ? '预约' : '挂号' }}
{{ (scope.row.healthcareName || '').replace('挂号', '') }}{{ scope.row.isFromAppointment ? $t('registration.appointmentCheckIn').slice(0,2) : $t('registration.saveRegistration').slice(0,2) }}
</span>
</template>
</vxe-column>
@@ -739,34 +739,34 @@
/> -->
<vxe-column
key="practitionerName"
title="专家"
:title="$t('registration.expert')"
align="center"
field="practitionerName"
:min-width="80"
/>
<vxe-column
key="contractName"
title="费用性质"
:title="$t('registration.feeNatureCol')"
align="center"
field="contractName"
:min-width="90"
/>
<vxe-column
key="totalPrice"
title="挂号金额"
:title="$t('registration.registrationAmount')"
align="center"
field="totalPrice"
:min-width="100"
>
<template #default="scope">
<span>
{{ scope.row.totalPrice ? scope.row.totalPrice.toFixed(2) + ' 元' : '0.00 元' }}
{{ scope.row.totalPrice ? scope.row.totalPrice.toFixed(2) + ' ' + $t('registration.yuan') : '0.00 ' + $t('registration.yuan') }}
</span>
</template>
</vxe-column>
<vxe-column
key="entererName"
title="收款人"
:title="$t('registration.cashier')"
align="center"
field="entererName"
:min-width="80"
@@ -786,7 +786,7 @@
<!-- <vxe-column title="证件号" align="center" key="idCard" field="idCard" width="180" /> -->
<vxe-column
key="statusEnum_enumText"
title="就诊状态"
:title="$t('registration.visitStatus')"
align="center"
field="statusEnum_enumText"
:min-width="90"
@@ -811,13 +811,13 @@
)
"
>
{{ scope.row.statusEnum_enumText || '未知' }}
{{ scope.row.statusEnum_enumText || $t('registration.unknown') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
key="registerTime"
title="挂号日期/时间"
:title="$t('registration.registrationDateTime')"
align="center"
field="registerTime"
width="180"
@@ -828,7 +828,7 @@
</vxe-column>
<vxe-column
key="operation"
title="操作"
:title="$t('registration.action')"
align="center"
field=""
width="150"
@@ -853,14 +853,14 @@
:disabled="scope.row.statusEnum == 6"
@click="handleReturn(scope.row, 1)"
>
退号
{{ $t('registration.returnRegistration') }}
</el-button>
<el-button
link
type="primary"
@click="handleReturn(scope.row, 0)"
>
详情
{{ $t('registration.detail') }}
</el-button>
</div>
<!-- </el-tooltip> -->
@@ -912,7 +912,7 @@
@close="
(value) => {
if (value == 'success') {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('registration.operationSuccess'));
getList();
}
openRefundDialog = false;
@@ -924,7 +924,7 @@
@close="
(value) => {
if (value == 'success') {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('registration.operationSuccess'));
getList();
}
openReprintDialog = false;
@@ -935,14 +935,14 @@
<!-- 预约签到患者选择弹窗 -->
<el-dialog
v-model="showCheckInPatientModal"
title="请选择预约的患者"
:title="$t('registration.selectAppointmentPatient')"
width="1200px"
:close-on-click-modal="false"
>
<div style="margin-bottom: 20px; display: flex; gap: 10px;">
<el-input
v-model="checkInSearchKey"
placeholder="输入患者姓名回车查询"
:placeholder="$t('registration.placeholderSearchAppointment')"
style="width: 400px"
@keyup.enter="loadCheckInPatientList"
/>
@@ -950,7 +950,7 @@
type="primary"
@click="loadCheckInPatientList"
>
查询
{{ $t('registration.query') }}
</el-button>
</div>
@@ -963,19 +963,19 @@
>
<vxe-column
type="seq"
title="序号"
:title="$t('registration.seqNo')"
width="60"
align="center"
/>
<vxe-column
field="patientId"
title="就诊卡号"
:title="$t('registration.cardNo')"
width="120"
align="center"
/>
<vxe-column
field="patientName"
title="姓名"
:title="$t('registration.name')"
width="120"
align="center"
>
@@ -985,45 +985,45 @@
</vxe-column>
<vxe-column
field="gender"
title="性别"
:title="$t('registration.gender')"
width="80"
align="center"
/>
<vxe-column
title="证件类型"
:title="$t('registration.idType')"
width="150"
align="center"
>
<template #default>
居民身份证
{{ $t('registration.residentIdCard') }}
</template>
</vxe-column>
<vxe-column
field="idCard"
title="证件号码"
:title="$t('registration.idNumber')"
width="200"
align="center"
/>
<vxe-column
field="phone"
title="手机号码"
:title="$t('registration.mobileNumber')"
width="150"
align="center"
/>
<vxe-column
title="号源类型"
:title="$t('registration.ticketType')"
width="100"
align="center"
>
<template #default="scope">
<el-tag :type="scope.row.ticketType === 'expert' ? 'danger' : 'success'">
{{ scope.row.ticketType === 'expert' ? '专家号' : '普通号' }}
{{ scope.row.ticketType === 'expert' ? $t('registration.expertTicket') : $t('registration.normalTicket') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
field="fee"
title="预约金额"
:title="$t('registration.appointmentAmount')"
width="100"
align="center"
>
@@ -1033,7 +1033,7 @@
</vxe-column>
<vxe-column
field="dateTime"
title="就诊时间"
:title="$t('registration.visitTime')"
width="180"
align="center"
/>
@@ -1049,14 +1049,14 @@
/>
<div class="dialog-footer">
<el-button @click="showCheckInPatientModal = false">
取消
{{ $t('common.cancel') }}
</el-button>
<el-button
type="primary"
:disabled="!selectedCheckInPatient"
@click="confirmCheckIn"
>
确定
{{ $t('common.confirm') }}
</el-button>
</div>
</div>
@@ -1084,7 +1084,8 @@ import { invokeYbPlugin5000, invokeYbPlugin5001 } from '@/api/public';
import patientInfoDialog from './components/patientInfoDialog';
import PatientAddDialog from './components/patientAddDialog';
import patientList from './components/patientList';
import {nextTick, onMounted, onUnmounted, ref} from 'vue';
import {nextTick, onMounted, onUnmounted, ref, computed} from 'vue';
import {useI18n} from 'vue-i18n';
import ChargeDialog from './components/chargeDialog.vue';
import RefundDialog from './components/refundDialog.vue';
import ReprintDialog from './components/reprintDialog.vue';
@@ -1096,6 +1097,8 @@ import {ElMessage, ElMessageBox} from 'element-plus';
import {hiprint} from 'vue-plugin-hiprint';
import outpatientRegistrationTemplate from '@/components/Print/OutpatientRegistration.json';
const {t} = useI18n();
const patientInfo = ref({});
const eventType = ref(0);
const router = useRouter();
@@ -1118,7 +1121,7 @@ const total = ref(0);
const title = ref('');
const BusiCardInfo = ref(''); // miyao
const priorityLevelOptionOptions = ref(undefined); // 优先级
const jzyyList = ref([{ value: '1', label: '其他' }]);
const jzyyList = computed(() => [{ value: '1', label: t('registration.other') }]);
const showPopover = ref(false);
const patientSearchKey = ref();
const chrgBchno = ref('');
@@ -1189,21 +1192,22 @@ const data = reactive({
// ybMatchFlag: undefined, // 是否医保匹配(包括 10
// status: undefined, // 状态(包括 1预置2启用3停用
},
rules: {
contractNo: [{ required: true, message: '费用性质', trigger: 'blur' }],
patientId: [{ required: true, message: '病人不能为空', trigger: 'blur' }],
priorityEnum: [{ required: true, message: '优先级不能为空', trigger: 'blur' }],
organizationId: [{ required: true, message: '优先级不能为空', trigger: 'blur' }],
orgId: [{ required: true, message: '就诊科室不能为空', trigger: 'blur' }],
serviceTypeId: [{ required: true, message: '挂号类型不能为空', trigger: 'blur' }],
practitionerId: [{ required: true, message: '医生不能为空', trigger: 'blur' }],
typeCode: [{ required: true, message: '账户类型不能为空', trigger: 'blur' }],
definitionId: [{ required: true, message: '费用定价不能为空', trigger: 'blur' }],
phone: [{ required: true, message: '联系电话不能为空', trigger: 'blur' }],
// totalPrice: [{ required: true, message: "总价不能为空", trigger: "blur" }],
},
rules: {},
});
const rules = computed(() => ({
contractNo: [{ required: true, message: t('registration.valFeeNatureRequired'), trigger: 'blur' }],
patientId: [{ required: true, message: t('registration.valPatientIdRequired'), trigger: 'blur' }],
priorityEnum: [{ required: true, message: t('registration.valPriorityRequired'), trigger: 'blur' }],
organizationId: [{ required: true, message: t('registration.valPriorityRequired'), trigger: 'blur' }],
orgId: [{ required: true, message: t('registration.valDepartmentRequired'), trigger: 'blur' }],
serviceTypeId: [{ required: true, message: t('registration.valRegTypeRequired'), trigger: 'blur' }],
practitionerId: [{ required: true, message: t('registration.valDoctorRequired'), trigger: 'blur' }],
typeCode: [{ required: true, message: t('registration.valAccountTypeRequired'), trigger: 'blur' }],
definitionId: [{ required: true, message: t('registration.valFeePricingRequired'), trigger: 'blur' }],
phone: [{ required: true, message: t('registration.valPhoneRequired'), trigger: 'blur' }],
}));
// 其他输入框和选择框的 ref
const inputs = [
contractNameRef,
@@ -1259,7 +1263,7 @@ onUnmounted(() => {
window.removeEventListener('keydown', handleKeyDown);
});
const { queryParams, form, rules } = toRefs(data);
const { queryParams, form } = toRefs(data);
/** 根据contractNo获取费用性质名称 */
function getFeeTypeName(contractNo) {
@@ -1282,7 +1286,7 @@ function getInitData() {
function handleSearch() {
console.log(form.value.searchKey, 'form.value.searchKey');
if (!form.value.searchKey) {
proxy.$modal.msgError('请输入查询内容');
proxy.$modal.msgError(t('registration.pleaseEnterQuery'));
return;
}
const param = {
@@ -1338,7 +1342,7 @@ async function handleReadCard(value) {
})
.then((res) => {
readCardLoading.value = true;
loadingText.value = '正在读取...';
loadingText.value = t('registration.readingCard');
console.log(res);
jsonResult = res.data;
})
@@ -1365,7 +1369,7 @@ async function handleReadCard(value) {
break;
case '03': // 社保卡
readCardLoading.value = true;
loadingText.value = '正在读取...';
loadingText.value = t('registration.readingCard');
await invokeYbPlugin5001(
JSON.stringify({
FunctionId: 1,
@@ -1881,7 +1885,7 @@ function handleAdd() {
if (!isValidCNPhoneNumber(patientInfo.value.phone)) {
ElMessage({
type: 'error',
message: '手机号格式不正确,请重新输入!',
message: t('registration.phoneFormatError'),
});
return;
}
@@ -1991,7 +1995,7 @@ function printRegistrationByHiprint(data) {
// 执行打印
hiprintTemplate.print2(result.data[0], {
title: '门诊挂号单',
title: t('registration.registrationSuccess'),
});
} catch (error) {
console.error('hiprint 打印挂号单失败:', error);
@@ -2032,7 +2036,7 @@ function handleReturn(row, type = 1) {
function handleReturnRegister() {
returnRegister(patientInfo.value.encounterId).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('registration.operationSuccess'));
getList();
}
});
@@ -2072,7 +2076,7 @@ function loadCheckInPatientList() {
checkInTotal.value = total;
}).catch(err => {
console.error('加载预约导出失败:', err);
ElMessage.error('获取预约列表失败');
ElMessage.error(t('registration.appointmentListFailed'));
}).finally(() => {
checkInLoading.value = false;
});
@@ -2086,7 +2090,7 @@ function selectRow(params) {
/** 确认签到(一键签到:直接构建挂号参数 → 预结算 → 弹收费窗口) */
async function confirmCheckIn() {
if (!selectedCheckInPatient.value) {
ElMessage.warning('请先选择患者');
ElMessage.warning(t('registration.pleaseSelectPatient'));
return;
}
@@ -2096,25 +2100,27 @@ async function confirmCheckIn() {
// 防御性校验:确保关键字段存在
if (!patient.departmentId) {
ElMessage.error('该号源缺少科室信息,无法完成签到,请联系管理员');
ElMessage.error(t('registration.missingDepartmentInfo'));
return;
}
if (!patient.realPatientId) {
ElMessage.error('该号源缺少患者信息,无法完成签到,请联系管理员');
ElMessage.error(t('registration.missingPatientInfo'));
return;
}
// 弹出确认提示
try {
await ElMessageBox.confirm(
`确认为患者【${patient.patientName || '未知患者'}】办理签到挂号?\n` +
`科室:${patient.department || '-'}\n` +
`医生:${patient.doctor || '-'}\n` +
`费用:¥${patient.fee || '0.00'}`,
'签到确认',
t('registration.confirmCheckInMsg', {
name: patient.patientName || t('registration.unknown'),
dept: patient.department || '-',
doctor: patient.doctor || '-',
fee: patient.fee || '0.00'
}),
t('registration.checkInConfirm'),
{
confirmButtonText: '确认签到',
cancelButtonText: '取消',
confirmButtonText: t('registration.confirmCheckIn'),
cancelButtonText: t('common.cancel'),
type: 'info',
}
);
@@ -2126,7 +2132,7 @@ async function confirmCheckIn() {
showCheckInPatientModal.value = false;
readCardLoading.value = true;
loadingText.value = '正在处理签到挂号...';
loadingText.value = t('registration.processingCheckIn');
try {
// 1. 用科室ID加载该科室的挂号类型列表获取 serviceTypeId 和 definitionId
@@ -2134,7 +2140,7 @@ async function confirmCheckIn() {
const healthcareRecords = healthcareRes.data?.records || [];
if (healthcareRecords.length === 0) {
ElMessage.error('该科室未配置挂号类型,无法自动签到');
ElMessage.error(t('registration.noRegistrationType'));
readCardLoading.value = false;
return;
}
@@ -2145,14 +2151,14 @@ async function confirmCheckIn() {
if (!matchedService) {
// 匹配不到就取第一个作为兜底
ElMessage.warning('未精确匹配到挂号类型,已使用默认类型');
ElMessage.warning(t('registration.noExactMatch'));
}
const service = matchedService || healthcareRecords[0];
const realPatientId = patient.realPatientId; // 后端新增的真实患者数据库ID
if (!realPatientId) {
ElMessage.error('患者ID缺失请联系管理员检查预约数据');
ElMessage.error(t('registration.patientIdMissing'));
readCardLoading.value = false;
return;
}
@@ -2225,12 +2231,12 @@ async function confirmCheckIn() {
printRegistrationByHiprint(res.data);
} else {
currentSlotId.value = null;
ElMessage.error(res.msg || '预结算失败');
ElMessage.error(res.msg || t('registration.preSettlementFailed'));
}
} catch (err) {
currentSlotId.value = null;
console.error('预约签到失败:', err);
ElMessage.error('签到处理失败: ' + (err.message || '未知错误'));
ElMessage.error(t('registration.checkInFailed') + (err.message || t('registration.unknown')));
} finally {
readCardLoading.value = false;
}
@@ -2306,8 +2312,8 @@ async function updatePhone() {
function handleClose(value) {
openDialog.value = false;
if (value == 'success') {
proxy.$modal.msgSuccess('操作成功');
// 更新患者手机号
proxy.$modal.msgSuccess(t('registration.operationSuccess'));
// 更新患者手机号
updatePhone();
// 先取出并清空,避免接口失败/取消等路径导致 slotId 残留污染下一单
@@ -2320,7 +2326,7 @@ function handleClose(value) {
console.log('预约状态已更新为已取号');
}).catch(err => {
console.error('更新预约状态失败:', err);
ElMessage.error('预约状态更新失败,请手动签到');
ElMessage.error(t('registration.insuranceUpdateFailed'));
});
}
} else if (value == 'cancel') {

View File

@@ -5,14 +5,14 @@
style="padding: 10px; border: 1px solid #eee; height: 50px; border-right: 0; display: flex; align-items: center; justify-content: space-between"
>
<div style="display: flex; align-items: center;">
<span style="margin-right: 20px; font-weight: 600;">现诊患者</span>
<span style="margin-right: 20px; font-weight: 600;">{{ $t('doctorstation.currentPatients') }}</span>
<el-button
type="primary"
size="small"
title="点击打开叫号界面"
:title="$t('doctorstation.openCallQueue')"
@click.stop="handleOpenCallDialog"
>
<i class="el-icon-bell" /> 呼叫
<i class="el-icon-bell" /> {{ $t('doctorstation.call') }}
</el-button>
</div>
<el-badge
@@ -23,13 +23,13 @@
<span
style="font-weight: 600;"
@click="openDrawer"
> 患者队列 </span>
> {{ $t('doctorstation.patientQueue') }} </span>
</el-badge>
</div>
<div style="width: 100%; padding: 10px">
<el-input
v-model="queryParams.searchKey"
placeholder="请输入患者名"
:placeholder="$t('doctorstation.searchPatientPlaceholder')"
clearable
style="width: 100%; margin-bottom: 10px"
@keyup.enter="getPatientList"
@@ -46,7 +46,7 @@
type="date"
style="width: 100%; margin-bottom: 10px"
:clearable="false"
placeholder="挂号时间"
:placeholder="$t('doctorstation.registrationTime')"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
@change="handleTimeChange"
@@ -74,7 +74,7 @@
tclass="name"
width="auto"
>
{{ item.patientName || '未知' }}
{{ item.patientName || $t('doctorstation.unknown') }}
</el-text>
</div>
</div>
@@ -98,7 +98,7 @@
tclass="name"
width="auto"
>
挂号时间
{{ $t('doctorstation.registrationTime') }}
</el-text>
<el-text
tclass="name"
@@ -116,7 +116,7 @@
tclass="name"
width="auto"
>
病历号
{{ $t('doctorstation.medicalRecordNo') }}
</el-text>
<el-text
tclass="name"
@@ -138,7 +138,7 @@
<div style="padding: 10px; border: 1px solid #eee; min-height: 50px; border-left: 0; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px;">
<div style="display: flex; align-items: flex-start; gap: 20px; flex: 1; flex-wrap: wrap;">
<div style="display: flex; align-items: flex-start;">
<span style="color: #606266; font-size: 14px; margin-right: 8px; flex-shrink: 0; line-height: 1.5;">患者信息:</span>
<span style="color: #606266; font-size: 14px; margin-right: 8px; flex-shrink: 0; line-height: 1.5;">{{ $t('doctorstation.patientInfo') }}:</span>
<span style="font-size: 14px; line-height: 1.5; word-break: break-all;">
{{
Object.keys(patientInfo).length !== 0
@@ -148,11 +148,11 @@
</span>
</div>
<div style="display: flex; align-items: center; flex-shrink: 0; line-height: 1.5;">
<span style="color: #606266; font-size: 14px; margin-right: 8px;">挂号时间:</span>
<span style="color: #606266; font-size: 14px; margin-right: 8px;">{{ $t('doctorstation.registrationTime') }}:</span>
<span style="font-size: 14px;">{{ Object.keys(patientInfo).length !== 0 ? formatDate(patientInfo.registerTime) : '-' }}</span>
</div>
<div style="display: flex; align-items: center; flex-shrink: 0; line-height: 1.5;">
<span style="color: #606266; font-size: 14px; margin-right: 8px;">医生:</span>
<span style="color: #606266; font-size: 14px; margin-right: 8px;">{{ $t('doctorstation.doctor') }}:</span>
<span style="font-size: 14px;">{{ userStore.nickName }}</span>
</div>
</div>
@@ -163,10 +163,10 @@
style="margin-right: 5px;"
>
<el-radio :value="1">
初诊
{{ $t('doctorstation.firstVisit') }}
</el-radio>
<el-radio :value="2">
复诊
{{ $t('doctorstation.followUp') }}
</el-radio>
</el-radio-group>
<el-button
@@ -175,7 +175,7 @@
size="small"
@click.stop="handleFinish(patientInfo.encounterId)"
>
完诊
{{ $t('doctorstation.finishVisit') }}
</el-button>
<el-button
type="primary"
@@ -183,7 +183,7 @@
size="small"
@click.stop="handleLeave(patientInfo.encounterId)"
>
暂离
{{ $t('doctorstation.temporaryLeave') }}
</el-button>
<el-button
type="warning"
@@ -192,7 +192,7 @@
size="small"
@click.stop="handleCancel(patientInfo.encounterId)"
>
取消接诊
{{ $t('doctorstation.cancelReception') }}
</el-button>
<el-button
type="primary"
@@ -201,7 +201,7 @@
size="small"
@click.stop="handleRefund(patientInfo.encounterId)"
>
退费
{{ $t('doctorstation.refund') }}
</el-button>
<el-button
type="primary"
@@ -210,7 +210,7 @@
size="small"
@click.stop="getEnPrescription(patientInfo.encounterId)"
>
处方单
{{ $t('doctorstation.prescription') }}
</el-button>
<el-button
type="primary"
@@ -220,7 +220,7 @@
size="small"
@click.stop="handleHospitalizationClick()"
>
办理住院
{{ $t('doctorstation.hospitalization') }}
</el-button>
</div>
</div>
@@ -232,7 +232,7 @@
@tab-change="handleClick(activeTab)"
>
<el-tab-pane
label="门诊病历"
:label="$t('doctorstation.outpatientRecord')"
name="hospitalizationEmr"
>
<hospitalizationEmr
@@ -257,7 +257,7 @@
/>
</el-tab-pane> -->
<el-tab-pane
label="诊断"
:label="$t('doctorstation.diagnosis')"
name="diagnosis"
>
<Diagnosis
@@ -271,7 +271,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="医嘱"
:label="$t('doctorstation.medicalAdvice')"
name="prescription"
>
<prescriptionlist
@@ -283,7 +283,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="中医"
:label="$t('doctorstation.tcm')"
name="tcm"
>
<tcmAdvice
@@ -292,7 +292,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="检验"
:label="$t('doctorstation.inspection')"
name="inspection"
>
<inspectionApplication
@@ -302,7 +302,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="检查"
:label="$t('doctorstation.examination')"
name="examination"
>
<examinationApplication
@@ -313,7 +313,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="手术申请"
:label="$t('doctorstation.surgeryApplication')"
name="surgery"
>
<surgeryApplication
@@ -324,7 +324,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="电子处方"
:label="$t('doctorstation.ePrescription')"
name="eprescription"
>
<eprescriptionlist
@@ -333,7 +333,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="报告查询"
:label="$t('doctorstation.reportQuery')"
name="reportQuery"
>
<ReportQuery
@@ -342,7 +342,7 @@
/>
</el-tab-pane>
<el-tab-pane
label="会诊"
:label="$t('doctorstation.consultation')"
name="consultation"
>
<Consultation
@@ -364,7 +364,7 @@
</div>
<el-drawer
v-model="drawer"
title="患者队列"
:title="$t('doctorstation.patientQueue')"
direction="ltr"
@open="handleOpen"
@closed="handleDrawerClosed"
@@ -398,7 +398,7 @@
:current-patient="currentCallPatient"
:current-patient-list="currentWaitPatientList"
:room-no="roomNo"
:department="userStore.orgName || patientInfo.organizationName || '心内科'"
:department="userStore.orgName || patientInfo.organizationName || $t('doctorstation.defaultDepartment')"
@call-next="callNext"
@re-call="reCall"
@finish="finishCall"
@@ -439,6 +439,7 @@ import InfectiousReport from './components/infectiousReport/index.vue';
import { formatDate, formatDateStr } from '@/utils/index';
import useUserStore from '@/store/modules/user';
import { nextTick } from 'vue';
import { useI18n } from 'vue-i18n';
import { updatePatientInfo } from './components/store/patient.js';
import { ElMessage, ElMessageBox } from 'element-plus';
@@ -473,6 +474,7 @@ watch(
);
const userStore = useUserStore();
const { t } = useI18n();
const bedfont = 'bed-font';
const queryParams = ref({
pageNo: 1,
@@ -554,13 +556,13 @@ const disabled = computed(() => {
// 当前逻辑保持不变,但我们将在按钮级别处理禁用状态
return Object.keys(patientInfo.value).length === 0;
});
const shortcuts = [
const shortcuts = computed(() => [
{
text: '今天',
text: t('doctorstation.today'),
value: new Date(),
},
{
text: '昨天',
text: t('doctorstation.yesterday'),
value: () => {
const date = new Date();
date.setDate(date.getDate() - 1);
@@ -568,7 +570,7 @@ const shortcuts = [
},
},
{
text: '三天内',
text: t('doctorstation.withinThreeDays'),
value: () => {
const date = new Date();
date.setDate(date.getDate() - 3);
@@ -576,14 +578,14 @@ const shortcuts = [
},
},
{
text: '一周内',
text: t('doctorstation.withinOneWeek'),
value: () => {
const date = new Date();
date.setDate(date.getDate() - 7);
return date;
},
},
];
]);
const eprescriptionRef = ref();
onMounted(() => {
@@ -767,7 +769,7 @@ function getEnPrescription(encounterId) {
if (dataArr.length <= 0) {
ElMessage({
type: 'error',
message: '暂无处方单',
message: t('doctorstation.noPrescription'),
});
return;
}
@@ -779,7 +781,7 @@ function getEnPrescription(encounterId) {
function handleRefund(encounterId) {
// 校验是否选择了患者
if (!encounterId) {
ElMessage.warning('请先选择患者后再进行退费操作');
ElMessage.warning(t('doctorstation.selectPatientForRefund'));
return;
}
currentEncounterId.value = encounterId;
@@ -864,7 +866,7 @@ function handleCardClick(item, index) {
function handleLeave(encounterId) {
leaveEncounter(encounterId).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('doctorstation.operationSuccess'));
patientInfo.value = {};
getPatientList();
}
@@ -873,26 +875,26 @@ function handleLeave(encounterId) {
function handleCancel(encounterId) {
if (!encounterId) {
ElMessage.warning('请先选择患者后再进行取消接诊操作');
ElMessage.warning(t('doctorstation.selectPatientForCancel'));
return;
}
ElMessageBox.confirm('确定要取消接诊该患者吗?取消后患者将回到待诊状态。', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
ElMessageBox.confirm(t('doctorstation.confirmCancelReception'), t('common.tip'), {
confirmButtonText: t('common.confirm'),
cancelButtonText: t('common.cancel'),
type: 'warning'
}).then(() => {
cancelEncounter(encounterId).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('取消接诊成功');
proxy.$modal.msgSuccess(t('doctorstation.cancelReceptionSuccess'));
patientInfo.value = {};
getPatientList();
getWaitPatient();
} else {
proxy.$modal.msgError(res.msg || '取消接诊失败');
proxy.$modal.msgError(res.msg || t('doctorstation.cancelReceptionFailed'));
}
}).catch((error) => {
console.error('取消接诊失败:', error);
proxy.$modal.msgError('取消接诊失败');
proxy.$modal.msgError(t('doctorstation.cancelReceptionFailed'));
});
}).catch(() => {
// 用户取消操作,不做处理
@@ -908,32 +910,32 @@ async function handleFinish(encounterId) {
// 检查是否有诊断
if (diagnosisList.length === 0) {
proxy.$modal.msgWarning('请先添加诊断信息');
proxy.$modal.msgWarning(t('doctorstation.addDiagnosisFirst'));
return;
}
// 检查诊断类型是否为空
const emptyMedType = diagnosisList.find(d => !d.medTypeCode);
if (emptyMedType) {
proxy.$modal.msgWarning('请选择诊断类型');
proxy.$modal.msgWarning(t('doctorstation.selectDiagnosisType'));
return;
}
// 检查是否有主诊断
if (!diagnosisList.some(d => d.maindiseFlag === 1)) {
proxy.$modal.msgWarning('请至少设置一条主诊断');
proxy.$modal.msgWarning(t('doctorstation.setMainDiagnosis'));
return;
}
}
} catch (error) {
console.error('获取诊断信息失败:', error);
proxy.$modal.msgWarning('获取诊断信息失败,请重试');
proxy.$modal.msgWarning(t('doctorstation.getDiagnosisFailed'));
return;
}
completeEncounter({ encounterId, firstEnum: firstEnum.value }).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess('操作成功');
proxy.$modal.msgSuccess(t('doctorstation.operationSuccess'));
patientInfo.value = {};
visitType.value = ''; // 重置初复诊标识
visitTypeDisabled.value = false; // 重置禁用状态
@@ -966,7 +968,7 @@ function handleHospitalizationClick() {
if (!patientInfo.value || !patientInfo.value.encounterId) {
console.log('患者信息不完整,无法办理住院');
ElMessage.warning('请先选择患者');
ElMessage.warning(t('doctorstation.selectPatient'));
} else {
console.log('调用onHospitalization函数');
onHospitalization();
@@ -990,7 +992,7 @@ function handleEmrSaved(isSaved) {
// 处理传染病报卡保存成功事件
function handleInfectiousReportSaved() {
// 可以在这里添加刷新列表或其他逻辑
proxy.$modal.msgSuccess('传染病报告卡保存成功');
proxy.$modal.msgSuccess(t('doctorstation.infectiousReportSaved'));
}
// 处理写病历事件
@@ -1021,7 +1023,7 @@ const onHospitalization = async () => {
console.log('缺少有效的就诊ID无法办理住院');
ElMessage({
type: 'error',
message: '患者就诊信息不完整,无法办理住院!',
message: t('doctorstation.patientEncounterIncomplete'),
});
return;
}
@@ -1036,7 +1038,7 @@ const onHospitalization = async () => {
console.log('获取诊断信息失败:', diagnosisRes.msg);
ElMessage({
type: 'error',
message: diagnosisRes.msg || '获取诊断信息失败,无法办理住院!',
message: diagnosisRes.msg || t('doctorstation.getDiagnosisFailed'),
});
return;
}
@@ -1046,11 +1048,11 @@ const onHospitalization = async () => {
if (!hasDiagnosis) {
console.log('该患者暂无诊断信息');
const confirmResult = await ElMessageBox.confirm(
'该患者暂无诊断信息,是否前往添加诊断?',
'提示',
t('doctorstation.noDiagnosisConfirm'),
t('common.tip'),
{
confirmButtonText: '前往添加',
cancelButtonText: '暂不办理',
confirmButtonText: t('doctorstation.goToAdd'),
cancelButtonText: t('common.cancel'),
type: 'warning',
}
).catch(() => {
@@ -1071,11 +1073,11 @@ const onHospitalization = async () => {
if (!mainDiag) {
console.log('该患者暂无主诊断信息');
const confirmResult = await ElMessageBox.confirm(
'该患者暂无主诊断信息,是否前往设置主诊断?',
'提示',
t('doctorstation.noMainDiagnosisConfirm'),
t('common.tip'),
{
confirmButtonText: '前往设置',
cancelButtonText: '暂不办理',
confirmButtonText: t('doctorstation.goToSet'),
cancelButtonText: t('common.cancel'),
type: 'warning',
}
).catch(() => {
@@ -1105,7 +1107,7 @@ const onHospitalization = async () => {
console.log('检查住院状态失败:', res.msg);
ElMessage({
type: 'error',
message: res.msg || '检查住院状态失败!',
message: res.msg || t('doctorstation.checkHospitalizationFailed'),
});
return;
}
@@ -1123,13 +1125,13 @@ const onHospitalization = async () => {
console.log('患者已办理过住院');
ElMessage({
type: 'error',
message: '该患者,已办理入院,不允许重复办理',
message: t('doctorstation.alreadyHospitalized'),
});
}
} catch (error) {
console.error('办理住院检查过程中发生错误:', error);
// 显示详细的错误信息
const errorMessage = error.message || error.msg || '办理住院过程中发生错误,请稍后重试!';
const errorMessage = error.message || error.msg || t('doctorstation.hospitalizationError');
ElMessage({
type: 'error',
message: errorMessage,

View File

@@ -9,36 +9,36 @@
class="query-form"
>
<el-form-item
label="字典名称"
:label="$t('system.dict.dictName')"
prop="dictName"
>
<el-input
v-model="queryParams.dictName"
placeholder="请输入字典名称"
:placeholder="$t('system.dict.placeholderDictName')"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item
label="字典类型"
:label="$t('system.dict.dictType')"
prop="dictType"
>
<el-input
v-model="queryParams.dictType"
placeholder="请输入字典类型"
:placeholder="$t('system.dict.placeholderDictType')"
clearable
style="width: 240px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item
label="状态"
:label="$t('common.status')"
prop="status"
>
<el-select
v-model="queryParams.status"
placeholder="字典状态"
:placeholder="$t('system.dict.dictStatus')"
clearable
style="width: 240px"
>
@@ -51,7 +51,7 @@
</el-select>
</el-form-item>
<el-form-item
label="创建时间"
:label="$t('common.createTime')"
style="width: 308px"
>
<el-date-picker
@@ -59,8 +59,8 @@
value-format="YYYY-MM-DD"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:start-placeholder="$t('system.dict.placeholderStartDate')"
:end-placeholder="$t('system.dict.placeholderEndDate')"
/>
</el-form-item>
<el-form-item class="search-buttons">
@@ -69,13 +69,13 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('common.search') }}
</el-button>
<el-button
icon="Refresh"
@click="resetQuery"
>
重置
{{ $t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -92,7 +92,7 @@
icon="Plus"
@click="handleAdd"
>
新增
{{ $t('common.add') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -104,7 +104,7 @@
:disabled="single"
@click="handleUpdate"
>
修改
{{ $t('common.edit') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -116,7 +116,7 @@
:disabled="multiple"
@click="handleDelete"
>
删除
{{ $t('common.delete') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -127,7 +127,7 @@
icon="Download"
@click="handleExport"
>
导出
{{ $t('common.export') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -138,7 +138,7 @@
icon="Refresh"
@click="handleRefreshCache"
>
刷新缓存
{{ $t('system.dict.refreshCache') }}
</el-button>
</el-col>
<right-toolbar
@@ -158,18 +158,18 @@
align="center"
/>
<vxe-column
title="字典编号"
:title="$t('system.dict.dictCode')"
align="center"
field="dictId"
/>
<vxe-column
title="字典名称"
:title="$t('system.dict.dictName')"
align="center"
field="dictName"
show-overflow="title"
/>
<vxe-column
title="字典类型"
:title="$t('system.dict.dictType')"
align="center"
show-overflow="title"
>
@@ -183,7 +183,7 @@
</template>
</vxe-column>
<vxe-column
title="状态"
:title="$t('common.status')"
align="center"
field="status"
>
@@ -196,13 +196,13 @@
</template>
</vxe-column>
<vxe-column
title="备注"
:title="$t('common.remark')"
align="center"
field="remark"
show-overflow="title"
/>
<vxe-column
title="创建时间"
:title="$t('common.createTime')"
align="center"
field="createTime"
width="180"
@@ -212,7 +212,7 @@
</template>
</vxe-column>
<vxe-column
title="操作"
:title="$t('common.operation')"
align="center"
width="160"
class-name="small-padding fixed-width"
@@ -226,7 +226,7 @@
class="action-button"
@click="handleUpdate(scope.row)"
>
修改
{{ $t('common.edit') }}
</el-button>
<el-button
v-hasPermi="['system:dict:remove']"
@@ -236,7 +236,7 @@
class="action-button"
@click="handleDelete(scope.row)"
>
删除
{{ $t('common.delete') }}
</el-button>
</template>
</vxe-column>
@@ -266,25 +266,25 @@
label-width="80px"
>
<el-form-item
label="字典名称"
:label="$t('system.dict.dictName')"
prop="dictName"
>
<el-input
v-model="form.dictName"
placeholder="请输入字典名称"
:placeholder="$t('system.dict.placeholderDictName')"
/>
</el-form-item>
<el-form-item
label="字典类型"
:label="$t('system.dict.dictType')"
prop="dictType"
>
<el-input
v-model="form.dictType"
placeholder="请输入字典类型"
:placeholder="$t('system.dict.placeholderDictType')"
/>
</el-form-item>
<el-form-item
label="状态"
:label="$t('common.status')"
prop="status"
>
<el-radio-group v-model="form.status">
@@ -300,13 +300,13 @@
</el-radio-group>
</el-form-item>
<el-form-item
label="备注"
:label="$t('common.remark')"
prop="remark"
>
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入内容"
:placeholder="$t('system.dict.enterContent')"
/>
</el-form-item>
</el-form>
@@ -316,10 +316,10 @@
type="primary"
@click="submitForm"
>
{{ $t('common.confirm') }}
</el-button>
<el-button @click="cancel">
{{ $t('common.cancel') }}
</el-button>
</div>
</template>
@@ -330,7 +330,9 @@
<script setup name="Dict">
import useDictStore from '@/store/modules/dict';
import { addType, delType, getType, listType, refreshCache, updateType, } from '@/api/system/dict/type';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const { sys_normal_disable } = proxy.useDict('sys_normal_disable');
@@ -354,13 +356,14 @@ const data = reactive({
dictType: undefined,
status: undefined,
},
rules: {
dictName: [{ required: true, message: '字典名称不能为空', trigger: 'blur' }],
dictType: [{ required: true, message: '字典类型不能为空', trigger: 'blur' }],
},
});
const { queryParams, form, rules } = toRefs(data);
const rules = computed(() => ({
dictName: [{ required: true, message: t('system.dict.valDictNameRequired'), trigger: 'blur' }],
dictType: [{ required: true, message: t('system.dict.valDictTypeRequired'), trigger: 'blur' }],
}));
const { queryParams, form } = toRefs(data);
/** 查询字典类型列表 */
function getList() {
@@ -402,7 +405,7 @@ function resetQuery() {
function handleAdd() {
reset();
open.value = true;
title.value = '添加字典类型';
title.value = t('system.dict.addDictType');
}
/** 多选框选中数据 */
function handleSelectionChange(selection) {
@@ -417,7 +420,7 @@ function handleUpdate(row) {
getType(dictId).then((response) => {
form.value = response.data;
open.value = true;
title.value = '修改字典类型';
title.value = t('system.dict.editDictType');
});
}
/** 提交按钮 */
@@ -426,13 +429,13 @@ function submitForm() {
if (valid) {
if (form.value.dictId !== undefined) {
updateType(form.value).then(() => {
proxy.$modal.msgSuccess('修改成功');
proxy.$modal.msgSuccess(t('message.editSuccess'));
open.value = false;
getList();
});
} else {
addType(form.value).then(() => {
proxy.$modal.msgSuccess('新增成功');
proxy.$modal.msgSuccess(t('message.addSuccess'));
open.value = false;
getList();
});
@@ -444,13 +447,13 @@ function submitForm() {
function handleDelete(row) {
const dictIds = row.dictId || ids.value;
proxy.$modal
.confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?')
.confirm(t('system.dict.deleteTypeConfirm', { id: dictIds }))
.then(function () {
return delType(dictIds);
})
.then(() => {
getList();
proxy.$modal.msgSuccess('删除成功');
proxy.$modal.msgSuccess(t('message.deleteSuccess'));
})
.catch(() => { });
}
@@ -467,7 +470,7 @@ function handleExport() {
/** 刷新缓存按钮操作 */
function handleRefreshCache() {
refreshCache().then(() => {
proxy.$modal.msgSuccess('刷新成功');
proxy.$modal.msgSuccess(t('system.dict.refreshSuccess'));
useDictStore().cleanDict();
});
}

View File

@@ -8,24 +8,24 @@
class="query-form"
>
<el-form-item
label="菜单名称"
:label="$t('system.menu.menuName')"
prop="menuName"
>
<el-input
v-model="queryParams.menuName"
placeholder="请输入菜单名称"
:placeholder="$t('system.menu.placeholderMenuName')"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item
label="状态"
:label="$t('common.status')"
prop="status"
>
<el-select
v-model="queryParams.status"
placeholder="菜单状态"
:placeholder="$t('system.menu.menuStatus')"
clearable
style="width: 200px"
>
@@ -38,12 +38,12 @@
</el-select>
</el-form-item>
<el-form-item
label="显示状态"
:label="$t('system.menu.menuVisible')"
prop="visible"
>
<el-select
v-model="queryParams.visible"
placeholder="显示状态"
:placeholder="$t('system.menu.menuVisible')"
clearable
style="width: 200px"
>
@@ -61,13 +61,13 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('common.search') }}
</el-button>
<el-button
icon="Refresh"
@click="resetQuery"
>
重置
{{ $t('common.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -84,7 +84,7 @@
icon="Plus"
@click="handleAdd"
>
新增
{{ $t('common.add') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -94,7 +94,7 @@
icon="Sort"
@click="toggleExpandAll"
>
展开/折叠
{{ $t('system.menu.expandCollapse') }}
</el-button>
</el-col>
<right-toolbar
@@ -114,7 +114,7 @@
>
<el-table-column
prop="menuName"
title="菜单名称"
:title="$t('system.menu.menuName')"
show-overflow-tooltip
width="160"
>
@@ -128,7 +128,6 @@
<span
v-else-if="scope.row.menuType === 'C'"
class="menu-name-link"
:title="`点击跳转到${scope.row.menuName}模块`"
style="cursor: pointer; color: #3B82F6;"
@click="handleMenuClick(scope.row)"
>
@@ -144,7 +143,7 @@
</el-table-column>
<el-table-column
prop="icon"
title="图标"
:title="$t('system.menu.icon')"
align="center"
width="100"
>
@@ -157,22 +156,22 @@
</el-table-column>
<el-table-column
prop="orderNum"
title="排序"
:title="$t('system.menu.menuSort')"
width="60"
/>
<el-table-column
prop="perms"
title="权限标识"
:title="$t('system.menu.menuPermi')"
show-overflow-tooltip
/>
<el-table-column
prop="path"
title="路由地址"
:title="$t('system.menu.menuPath')"
show-overflow-tooltip
/>
<el-table-column
prop="fullPath"
title="完整路径"
:title="$t('system.menu.fullPath')"
show-overflow-tooltip
>
<template #default="scope">
@@ -182,12 +181,12 @@
</el-table-column>
<el-table-column
prop="component"
title="组件路径"
:title="$t('system.menu.menuComponent')"
show-overflow-tooltip
/>
<el-table-column
prop="status"
title="状态"
:title="$t('common.status')"
width="80"
>
<template #default="scope">
@@ -201,7 +200,7 @@
</el-table-column>
<el-table-column
prop="visible"
title="显示状态"
:title="$t('system.menu.menuVisible')"
width="100"
>
<template #default="scope">
@@ -214,7 +213,7 @@
</template>
</el-table-column>
<el-table-column
title="创建时间"
:title="$t('common.createTime')"
align="center"
width="160"
prop="createTime"
@@ -224,7 +223,7 @@
</template>
</el-table-column>
<el-table-column
title="操作"
:title="$t('common.operation')"
align="center"
width="210"
class-name="small-padding fixed-width"
@@ -238,7 +237,7 @@
class="action-button"
@click="handleUpdate(scope.row)"
>
修改
{{ $t('common.edit') }}
</el-button>
<el-button
v-hasPermi="['system:menu:add']"
@@ -248,7 +247,7 @@
class="action-button"
@click="handleAdd(scope.row)"
>
新增
{{ $t('common.add') }}
</el-button>
<el-button
v-hasPermi="['system:menu:remove']"
@@ -258,7 +257,7 @@
class="action-button"
@click="handleDelete(scope.row)"
>
删除
{{ $t('common.delete') }}
</el-button>
</template>
</el-table-column>
@@ -279,31 +278,31 @@
>
<el-row>
<el-col :span="24">
<el-form-item label="上级菜单">
<el-form-item :label="$t('system.menu.parentMenu')">
<el-tree-select
v-model="form.parentId"
:data="menuOptions"
:props="{ value: 'menuId', label: 'menuName', children: 'children' }"
value-key="menuId"
placeholder="选择上级菜单"
:placeholder="$t('system.menu.placeholderSelectParent')"
check-strictly
/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item
label="菜单类型"
:label="$t('system.menu.menuType')"
prop="menuType"
>
<el-radio-group v-model="form.menuType">
<el-radio value="M">
目录
{{ $t('system.menu.menuTypeDir') }}
</el-radio>
<el-radio value="C">
菜单
{{ $t('system.menu.menuTypeMenu') }}
</el-radio>
<el-radio value="F">
按钮
{{ $t('system.menu.menuTypeButton') }}
</el-radio>
</el-radio-group>
</el-form-item>
@@ -313,7 +312,7 @@
:span="24"
>
<el-form-item
label="菜单图标"
:label="$t('system.menu.menuIcon')"
prop="icon"
>
<el-popover
@@ -324,7 +323,7 @@
<template #reference>
<el-input
v-model="form.icon"
placeholder="点击选择图标"
:placeholder="$t('system.menu.placeholderClickIcon')"
readonly
@blur="showSelectIcon"
>
@@ -354,18 +353,18 @@
</el-col>
<el-col :span="12">
<el-form-item
label="菜单名称"
:label="$t('system.menu.menuName')"
prop="menuName"
>
<el-input
v-model="form.menuName"
placeholder="请输入菜单名称"
:placeholder="$t('system.menu.placeholderMenuName')"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="显示排序"
:label="$t('system.menu.menuSort')"
prop="orderNum"
>
<el-input-number
@@ -383,19 +382,19 @@
<template #label>
<span>
<el-tooltip
content="选择是外链则路由地址需要以`http(s)://`开头"
:content="$t('system.menu.tooltipExternalLink')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>是否外链
</el-tooltip>{{ $t('system.menu.isExternalLink') }}
</span>
</template>
<el-radio-group v-model="form.isFrame">
<el-radio value="0">
{{ $t('common.yes') }}
</el-radio>
<el-radio value="1">
{{ $t('common.no') }}
</el-radio>
</el-radio-group>
</el-form-item>
@@ -408,17 +407,17 @@
<template #label>
<span>
<el-tooltip
content="访问的路由地址,如:`user`,如外网地址需内链访问则以`http(s)://`开头"
:content="$t('system.menu.tooltipRoutePath')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
路由地址
{{ $t('system.menu.menuPath') }}
</span>
</template>
<el-input
v-model="form.path"
placeholder="请输入路由地址"
:placeholder="$t('system.menu.placeholderRoutePath')"
/>
</el-form-item>
</el-col>
@@ -426,11 +425,11 @@
v-if="form.menuType != 'F' && form.fullPath"
:span="24"
>
<el-form-item label="完整路径">
<el-form-item :label="$t('system.menu.fullPath')">
<el-input
v-model="form.fullPath"
readonly
placeholder="完整路径"
:placeholder="$t('system.menu.fullPath')"
/>
</el-form-item>
</el-col>
@@ -442,17 +441,17 @@
<template #label>
<span>
<el-tooltip
content="访问的组件路径,如:`system/user/index`,默认在`views`目录下"
:content="$t('system.menu.tooltipComponent')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
组件路径
{{ $t('system.menu.menuComponent') }}
</span>
</template>
<el-input
v-model="form.component"
placeholder="请输入组件路径"
:placeholder="$t('system.menu.placeholderComponent')"
/>
</el-form-item>
</el-col>
@@ -463,18 +462,18 @@
<el-form-item>
<el-input
v-model="form.perms"
placeholder="请输入权限标识"
:placeholder="$t('system.menu.placeholderPermi')"
maxlength="100"
/>
<template #label>
<span>
<el-tooltip
content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasPermi('system:user:list')`)"
:content="$t('system.menu.tooltipPermi')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
权限字符
{{ $t('system.menu.menuPermi') }}
</span>
</template>
</el-form-item>
@@ -486,18 +485,18 @@
<el-form-item>
<el-input
v-model="form.query"
placeholder="请输入路由参数"
:placeholder="$t('system.menu.placeholderRouteParam')"
maxlength="255"
/>
<template #label>
<span>
<el-tooltip
content="访问路由的默认传递参数,如:`{&quot;id&quot;: 1, &quot;name&quot;: &quot;ry&quot;}`"
:content="$t('system.menu.tooltipRouteParam')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
路由参数
{{ $t('system.menu.routeParam') }}
</span>
</template>
</el-form-item>
@@ -510,20 +509,20 @@
<template #label>
<span>
<el-tooltip
content="选择是则会被`keep-alive`缓存,需要匹配组件的`name`和地址保持一致"
:content="$t('system.menu.tooltipCache')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
是否缓存
{{ $t('system.menu.isCache') }}
</span>
</template>
<el-radio-group v-model="form.isCache">
<el-radio value="0">
缓存
{{ $t('system.menu.cacheYes') }}
</el-radio>
<el-radio value="1">
不缓存
{{ $t('system.menu.cacheNo') }}
</el-radio>
</el-radio-group>
</el-form-item>
@@ -536,12 +535,12 @@
<template #label>
<span>
<el-tooltip
content="选择隐藏则路由将不会出现在侧边栏,但仍然可以访问"
:content="$t('system.menu.tooltipVisible')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
显示状态
{{ $t('system.menu.menuVisible') }}
</span>
</template>
<el-radio-group v-model="form.visible">
@@ -560,12 +559,12 @@
<template #label>
<span>
<el-tooltip
content="选择停用则路由将不会出现在侧边栏,也不能被访问"
:content="$t('system.menu.tooltipMenuStatus')"
placement="top"
>
<el-icon><question-filled /></el-icon>
</el-tooltip>
菜单状态
{{ $t('system.menu.menuStatus') }}
</span>
</template>
<el-radio-group v-model="form.status">
@@ -587,10 +586,10 @@
type="primary"
@click="submitForm"
>
{{ $t('common.confirm') }}
</el-button>
<el-button @click="cancel">
{{ $t('common.cancel') }}
</el-button>
</div>
</template>
@@ -603,7 +602,9 @@ import {addMenu, delMenu, getMenu, listMenu, updateMenu, treeselect, refreshMenu
import SvgIcon from "@/components/SvgIcon";
import IconSelect from "@/components/IconSelect";
import {getNormalPath} from "@/utils/his";
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { proxy } = getCurrentInstance();
const { sys_show_hide, sys_normal_disable } = proxy.useDict("sys_show_hide", "sys_normal_disable");
@@ -611,14 +612,14 @@ const { sys_show_hide, sys_normal_disable } = proxy.useDict("sys_show_hide", "sy
const processedSysShowHide = computed(() => {
return sys_show_hide.value.map(item => ({
...item,
elTagType: item.elTagType || '' // 如果elTagType为null或undefined则设为空字符串
elTagType: item.elTagType || ''
}));
});
const processedSysNormalDisable = computed(() => {
return sys_normal_disable.value.map(item => ({
...item,
elTagType: item.elTagType || '' // 如果elTagType为null或undefined则设为空字符串
elTagType: item.elTagType || ''
}));
});
@@ -638,21 +639,21 @@ const data = reactive({
menuName: undefined,
visible: undefined
},
rules: {
menuName: [{ required: true, message: "菜单名称不能为空", trigger: "blur" }],
orderNum: [{ required: true, message: "菜单顺序不能为空", trigger: "blur" }],
path: [{ required: true, message: "路由地址不能为空", trigger: "blur" }]
},
});
const { queryParams, form, rules } = toRefs(data);
const rules = computed(() => ({
menuName: [{ required: true, message: t('system.menu.valMenuNameRequired'), trigger: "blur" }],
orderNum: [{ required: true, message: t('system.menu.valOrderNumRequired'), trigger: "blur" }],
path: [{ required: true, message: t('system.menu.valPathRequired'), trigger: "blur" }]
}));
const { queryParams, form } = toRefs(data);
/** 查询菜单列表 */
async function getList() {
loading.value = true;
try {
const response = await listMenu(queryParams.value);
// 后端已经返回了带完整路径的菜单树,直接使用即可
menuList.value = response.data;
} catch (error) {
console.error('获取菜单列表失败:', error);
@@ -664,23 +665,18 @@ async function getList() {
/** 刷新缓存并重新获取菜单列表 */
async function handleRefresh() {
try {
// 首先调用后端接口刷新缓存
await refreshMenuCache();
// 然后重新获取菜单列表
await getList();
proxy.$modal.msgSuccess("菜单缓存已刷新,列表已更新");
proxy.$modal.msgSuccess(t('system.menu.cacheRefreshed'));
} catch (error) {
console.error('刷新菜单缓存失败:', error);
proxy.$modal.msgError("刷新菜单缓存失败");
proxy.$modal.msgError(t('system.menu.cacheRefreshFailed'));
}
}
/** 查询菜单下拉树结构 */
function getTreeselect() {
menuOptions.value = [];
// 使用专门的treeselect API它返回预构建的树形结构
treeselect().then(response => {
// TreeSelect对象使用id、label、children字段但el-tree-select组件期望menuId、menuName、children字段
// 需要将TreeSelect对象转换为el-tree-select组件期望的格式
const convertTreeSelectToMenuFormat = (treeSelectList) => {
return treeSelectList.map(item => ({
menuId: item.id,
@@ -693,9 +689,9 @@ function getTreeselect() {
const rootNode = {
menuId: 0,
menuName: "主类目",
menuName: t('system.menu.rootCategory'),
value: 0,
label: "主类目",
label: t('system.menu.rootCategory'),
children: convertTreeSelectToMenuFormat(response.data)
};
menuOptions.value.push(rootNode);
@@ -745,14 +741,13 @@ async function handleAdd(row) {
await getTreeselect();
if (row != null && row.menuId) {
form.value.parentId = row.menuId;
// 使用后端返回的完整路径
form.value.parentFullPath = row.fullPath || row.path;
} else {
form.value.parentId = 0;
form.value.parentFullPath = '';
}
open.value = true;
title.value = "添加菜单";
title.value = t('system.menu.addMenu');
}
/** 展开/折叠操作 */
function toggleExpandAll() {
@@ -769,10 +764,9 @@ async function handleUpdate(row) {
try {
const response = await getMenu(row.menuId);
form.value = response.data;
// 使用后端返回的完整路径
form.value.fullPath = response.data.fullPath || response.data.path;
open.value = true;
title.value = "修改菜单";
title.value = t('system.menu.editMenu');
} catch (error) {
console.error('获取菜单信息失败:', error);
}
@@ -784,31 +778,28 @@ function submitForm() {
if (form.value.menuId != undefined) {
updateMenu(form.value).then(data => {
if (data === -1) {
proxy.$modal.msgError("路由地址已存在");
proxy.$modal.msgError(t('system.menu.routePathExists'));
} else {
proxy.$modal.msgSuccess("修改成功");
proxy.$modal.msgSuccess(t('message.editSuccess'));
open.value = false;
getList();
}
}).catch(() => {
// 可以在这里添加自定义的错误处理,或者使用默认的错误提示
proxy.$modal.msgError("路由地址已存在");
proxy.$modal.msgError(t('system.menu.routePathExists'));
});
} else {
addMenu(form.value).then(data => {
if (data === -1) {
proxy.$modal.msgError("路由地址已存在");
proxy.$modal.msgError(t('system.menu.routePathExists'));
} else {
proxy.$modal.msgSuccess("新增成功");
proxy.$modal.msgSuccess(t('message.addSuccess'));
open.value = false;
// 新增菜单后,刷新缓存并重新获取列表
refreshMenuCache().finally(() => {
getList();
});
}
}).catch(() => {
// 可以在这里添加自定义的错误处理,或者使用默认的错误提示
proxy.$modal.msgError("路由地址已存在");
proxy.$modal.msgError(t('system.menu.routePathExists'));
});
}
}
@@ -816,76 +807,63 @@ function submitForm() {
}
/** 删除按钮操作 */
function handleDelete(row) {
proxy.$modal.confirm('是否确认删除名称为"' + row.menuName + '"的数据项?').then(function() {
proxy.$modal.confirm(t('system.menu.deleteConfirm', { name: row.menuName })).then(function() {
return delMenu(row.menuId);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
proxy.$modal.msgSuccess(t('message.deleteSuccess'));
}).catch(() => {});
}
/** 处理菜单点击事件,跳转到对应功能模块 */
function handleMenuClick(row) {
// 只有菜单类型(C)才会进入此函数,因为模板中已限制
// 检查菜单是否有对应的路由路径
if (!row.path) {
proxy.$modal.msgWarning(`${row.menuName} 暂无对应的功能模块`);
proxy.$modal.msgWarning(t('system.menu.noModuleAvailable', { name: row.menuName }));
return;
}
// 如果是外部链接,新开窗口打开
if (row.isFrame === '0' && (row.path.startsWith('http://') || row.path.startsWith('https://'))) {
window.open(row.path, '_blank');
return;
}
// 使用完整路径作为主要路径,但如果它包含 /system 前缀而原始路径不包含,
// 则使用原始路径,以避免路由系统添加额外的 /system 前缀
let routePath = row.fullPath || row.path;
// 特殊处理:如果完整路径以 /system/ 开头,但菜单本身路径不包含 /system/
// 则使用菜单路径,避免重复添加 /system 前缀
if (row.fullPath && row.path &&
row.fullPath.startsWith('/system/') &&
!row.path.startsWith('/system/')) {
routePath = row.path;
}
// 确保路径以 / 开头
if (!routePath.startsWith('/')) {
routePath = '/' + routePath;
}
// 规范化路径,处理可能的路径问题
const normalizedPath = getNormalPath(routePath);
// 尝试导航到对应路由
try {
// 使用 router.push 导航到目标路由
proxy.$router.push({
path: normalizedPath
}).catch(err => {
// 如果路由导航失败,尝试另一种方式
console.error(`路由导航失败,尝试备用方案: ${normalizedPath}`, err);
// 尝试使用 name 进行路由跳转(如果菜单有路由名称)
if (row.routeName) {
try {
proxy.$router.push({ name: row.routeName }).catch(nameErr => {
console.error(`使用路由名称跳转也失败: ${row.routeName}`, nameErr);
proxy.$modal.msgError(`${row.menuName} 模块暂无法访问,请检查权限或联系管理员`);
proxy.$modal.msgError(t('system.menu.moduleAccessFailed', { name: row.menuName }));
});
} catch (nameErr) {
console.error(`使用路由名称跳转异常: ${row.routeName}`, nameErr);
proxy.$modal.msgError(`${row.menuName} 模块跳转失败`);
proxy.$modal.msgError(t('system.menu.moduleNavigateFailed', { name: row.menuName }));
}
} else {
proxy.$modal.msgError(`${row.menuName} 模块暂无法访问,请检查权限或联系管理员`);
proxy.$modal.msgError(t('system.menu.moduleAccessFailed', { name: row.menuName }));
}
});
} catch (error) {
console.error(`跳转到 ${row.menuName} 模块失败:`, error);
proxy.$modal.msgError(`${row.menuName} 模块跳转失败`);
proxy.$modal.msgError(t('system.menu.moduleNavigateFailed', { name: row.menuName }));
}
}