refactor: 国际化文本迁移至全局 locales/messages.js

将组件级 i18n 对象重构为统一由全局 locales/messages.js 管理,确保中英文语言切换时正确显示对应文本。

- 新增 utils/i18n.js 国际化工具函数
- 更新 store/$t.mixin.js 翻译混入逻辑
- 迁移 pkgService、pkgBooking、pkgAccount、pkgExplore、pages 等共 58 个组件的中英文文本至全局消息表
This commit is contained in:
liangjian
2026-07-24 13:43:41 +08:00
parent 445bd850f4
commit 6e721ccc7e
58 changed files with 1810 additions and 4065 deletions

View File

@@ -15,7 +15,7 @@
<view class="hero-header tn-margin-bottom-xl">
<view class="hero-badge">
<text class="badge-dot"></text>
<text>{{ t('ticketKicker') }}</text>
<text>{{ $tr('WORK ORDER') }}</text>
</view>
<view class="hero-title">{{ pageTitle }}</view>
<view class="hero-desc">{{ pageDesc }}</view>
@@ -27,35 +27,35 @@
:class="{ 'segment-item--active': activeTab === 'submit' }"
@click="switchTab('submit')"
>
{{ t('submitTab') }}
{{ $tr('提交申请') }}
</view>
<view
class="segment-item"
:class="{ 'segment-item--active': activeTab === 'history' }"
@click="switchTab('history')"
>
{{ t('historyTab') }}
{{ $tr('记录查询') }}
</view>
</view>
<view v-if="activeTab === 'submit'" class="context-card tn-margin-bottom-lg">
<view class="block-title">{{ t('currentStayInfo') }}</view>
<view class="block-title">{{ $tr('当前入住信息') }}</view>
<view class="block-subtitle">{{ currentOrderStatusText }}</view>
<view class="context-grid tn-margin-top">
<view class="context-item">
<view class="context-label">{{ t('roomLabel') }}</view>
<view class="context-label">{{ $tr('当前房间') }}</view>
<view class="context-value">{{ currentRoomText }}</view>
</view>
<view v-if="currentAreaText" class="context-item">
<view class="context-label">{{ t('areaLabel') }}</view>
<view class="context-label">{{ $tr('所属区域') }}</view>
<view class="context-value">{{ currentAreaText }}</view>
</view>
<view v-if="currentLeaseText" class="context-item">
<view class="context-label">{{ t('leaseLabel') }}</view>
<view class="context-label">{{ $tr('租期') }}</view>
<view class="context-value">{{ currentLeaseText }}</view>
</view>
<view v-if="currentRoomTypeText" class="context-item">
<view class="context-label">{{ t('roomTypeLabel') }}</view>
<view class="context-label">{{ $tr('当前房型') }}</view>
<view class="context-value">{{ currentRoomTypeText }}</view>
</view>
</view>
@@ -64,8 +64,8 @@
<view v-if="modeBannerText && activeTab === 'submit'" class="status-card tn-margin-bottom-lg" :class="statusCardClass">
<view class="status-card__title">{{ modeBannerTitle }}</view>
<view class="status-card__desc">{{ modeBannerText }}</view>
<view v-if="fixOnholdMode" class="status-card__action" @click="cancelFixOnhold">{{ t('cancelSupplement') }}</view>
<view v-else-if="transitActionMode" class="status-card__action" @click="cancelTransitAction">{{ t('cancelProcess') }}</view>
<view v-if="fixOnholdMode" class="status-card__action" @click="cancelFixOnhold">{{ $tr('取消补充') }}</view>
<view v-else-if="transitActionMode" class="status-card__action" @click="cancelTransitAction">{{ $tr('退出处理') }}</view>
</view>
<view v-if="activeTab === 'submit'" class="form-card">
@@ -73,7 +73,7 @@
<view class="block-subtitle">{{ submitSectionDesc }}</view>
<view v-if="isChangeService" class="form-item tn-margin-top">
<view class="form-label">{{ t('changeRoomTypeLabel') }}</view>
<view class="form-label">{{ $tr('意向房型') }}</view>
<room-type-selector
v-model="switchForm.roomTypeCode"
:initial-area-code="switchForm.areaCode"
@@ -82,37 +82,37 @@
</view>
<view v-if="isCheckOutService" class="form-item tn-margin-top">
<view class="form-label">{{ t('checkoutTimeLabel') }}</view>
<view class="form-label">{{ $tr('预计退宿时间') }}</view>
<view class="picker-row">
<picker mode="date" :value="form.checkOutDate" @change="onDateChange('checkOutDate', $event)">
<view class="form-picker">{{ form.checkOutDate || t('selectDate') }}</view>
<view class="form-picker">{{ form.checkOutDate || $tr('请选择日期') }}</view>
</picker>
<picker mode="time" :value="form.checkOutTimePart" @change="onTimeChange('checkOutTimePart', $event)">
<view class="form-picker form-picker--time">{{ form.checkOutTimePart || t('selectTime') }}</view>
<view class="form-picker form-picker--time">{{ form.checkOutTimePart || $tr('请选择时间') }}</view>
</picker>
</view>
</view>
<view v-if="isRenewalService" class="form-item tn-margin-top">
<view class="form-label">{{ t('renewalTimeLabel') }}</view>
<view class="form-label">{{ $tr('续住至') }}</view>
<view class="picker-row">
<picker mode="date" :value="form.renewalDate" @change="onDateChange('renewalDate', $event)">
<view class="form-picker">{{ form.renewalDate || t('selectDate') }}</view>
<view class="form-picker">{{ form.renewalDate || $tr('请选择日期') }}</view>
</picker>
<picker mode="time" :value="form.renewalTimePart" @change="onTimeChange('renewalTimePart', $event)">
<view class="form-picker form-picker--time">{{ form.renewalTimePart || t('selectTime') }}</view>
<view class="form-picker form-picker--time">{{ form.renewalTimePart || $tr('请选择时间') }}</view>
</picker>
</view>
</view>
<view v-if="isCleaningService" class="form-item tn-margin-top">
<view class="form-label">{{ t('cleaningTimeLabel') }}</view>
<view class="form-label">{{ $tr('预约清洁时间') }}</view>
<view class="picker-row">
<picker mode="date" :value="form.cleaningDate" @change="onDateChange('cleaningDate', $event)">
<view class="form-picker">{{ form.cleaningDate || t('selectDate') }}</view>
<view class="form-picker">{{ form.cleaningDate || $tr('请选择日期') }}</view>
</picker>
<picker mode="time" :value="form.cleaningTimePart" @change="onTimeChange('cleaningTimePart', $event)">
<view class="form-picker form-picker--time">{{ form.cleaningTimePart || t('selectTime') }}</view>
<view class="form-picker form-picker--time">{{ form.cleaningTimePart || $tr('请选择时间') }}</view>
</picker>
</view>
</view>
@@ -129,26 +129,26 @@
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('remarkLabel') }}</view>
<view class="form-label">{{ $tr('补充说明') }}</view>
<textarea
class="form-textarea form-textarea--remark"
:placeholder="t('remarkPlaceholder')"
:placeholder="$tr('请输入补充说明,帮助工作人员更快处理')"
:maxlength="300"
v-model="form.remark"
></textarea>
</view>
<view v-if="showTransitAssigneeSelector" class="form-item tn-margin-top">
<view class="form-label">{{ t('assigneeLabel') }}</view>
<view class="form-label">{{ $tr('处理目标') }}</view>
<picker mode="selector" :range="transitAssigneePickerLabels" @change="onTransitAssigneeChange">
<view class="form-picker">
{{ transitSelectedAssigneeName || t('selectAssignee') }}
{{ transitSelectedAssigneeName || $tr('请选择处理目标') }}
</view>
</picker>
</view>
<view v-if="fixOnholdMode && fixOnholdFields.length" class="form-item tn-margin-top">
<view class="form-label">{{ t('supplementLabel') }}</view>
<view class="form-label">{{ $tr('补充业务信息') }}</view>
<view
v-for="(item, index) in fixOnholdFields"
:key="`${item.key}-${index}`"
@@ -159,20 +159,20 @@
v-if="shouldUseTextarea(item.value)"
class="form-textarea form-textarea--small"
v-model="item.value"
:placeholder="t('supplementPlaceholder', { label: item.title })"
:placeholder="$tr('请输入{label}', { label: item.title })"
></textarea>
<input
v-else
class="form-input"
type="text"
v-model="item.value"
:placeholder="t('supplementPlaceholder', { label: item.title })"
:placeholder="$tr('请输入{label}', { label: item.title })"
/>
</view>
</view>
<view class="form-item tn-margin-top">
<view class="form-label">{{ t('attachmentsLabel') }}<text v-if="isRepairService" class="required-mark"> *</text></view>
<view class="form-label">{{ $tr('附件图片') }}<text v-if="isRepairService" class="required-mark"> *</text></view>
<tn-image-upload
:key="uploadInstanceKey"
:fileList="form.photos"
@@ -192,7 +192,7 @@
<template #addBtn>
<view class="upload-trigger">
<text class="tn-icon-camera-fill upload-trigger__icon"></text>
<view class="upload-trigger__text">{{ t('uploadImage') }}</view>
<view class="upload-trigger__text">{{ $tr('上传图片') }}</view>
</view>
</template>
</tn-image-upload>
@@ -207,13 +207,13 @@
<input
v-model="searchKeyword"
class="search-box__input"
:placeholder="t('searchPlaceholder')"
:placeholder="$tr('搜索工单标题或内容')"
confirm-type="search"
@confirm="refreshHistory"
/>
</view>
<view class="refresh-mini-btn" @click="refreshHistory">
{{ historyLoading ? t('refreshing') : t('refresh') }}
{{ historyLoading ? $tr('刷新中...') : $tr('刷新') }}
</view>
</view>
@@ -249,26 +249,26 @@
</view>
<view class="history-card__body tn-margin-top">
<view class="info-row tn-flex tn-flex-row-between">
<text class="info-label">{{ t('submittedAtLabel') }}</text>
<text class="info-label">{{ $tr('提交时间') }}</text>
<text class="info-value">{{ formatDateTime(item.createTime) }}</text>
</view>
<view class="info-row tn-flex tn-flex-row-between">
<text class="info-label">{{ t('contentLabel') }}</text>
<text class="info-label">{{ $tr('申请内容') }}</text>
<text class="info-value info-value--multiline">{{ item.content || item.remark || '--' }}</text>
</view>
</view>
</view>
<view class="load-state">
<text v-if="historyLoading">{{ t('loadingMore') }}</text>
<text v-else-if="!hasNext">{{ t('noMore') }}</text>
<text v-else @click="loadMoreHistory">{{ t('loadMore') }}</text>
<text v-if="historyLoading">{{ $tr('加载中...') }}</text>
<text v-else-if="!hasNext">{{ $tr('没有更多了') }}</text>
<text v-else @click="loadMoreHistory">{{ $tr('加载更多') }}</text>
</view>
</view>
<view v-else-if="!historyLoading" class="empty-panel tn-padding-lg">
<view class="empty-title">{{ t('emptyHistoryTitle') }}</view>
<view class="empty-desc tn-margin-top-sm">{{ t('emptyHistoryDesc') }}</view>
<view class="empty-title">{{ $tr('暂无工单记录') }}</view>
<view class="empty-desc tn-margin-top-sm">{{ $tr('当前类型还没有工单记录。') }}</view>
</view>
</view>
</view>
@@ -278,7 +278,7 @@
<view class="floating-submit-bar__inner">
<view class="floating-submit-tip">{{ submitFooterTip }}</view>
<view class="submit-btn btn-primary" :class="{ 'submit-btn--disabled': submitting }" @click="submitForm">
<text class="tn-text-bold">{{ submitting ? t('submitting') : submitButtonText }}</text>
<text class="tn-text-bold">{{ submitting ? $tr('提交中...') : submitButtonText }}</text>
</view>
</view>
</view>
@@ -298,10 +298,10 @@
<view class="flow-card__status">{{ getFlowStatusText(item) }}</view>
<view class="flow-card__time tn-margin-top-xs">{{ formatDateTime(item.createTime) }}</view>
</view>
<view v-if="isCurrentFlowItem(index)" class="flow-card__tag">{{ t('currentFlowTag') }}</view>
<view v-if="isCurrentFlowItem(index)" class="flow-card__tag">{{ $tr('当前节点') }}</view>
</view>
<view class="flow-card__content tn-margin-top">{{ item.content || item.remark || t('noFlowContent') }}</view>
<view class="flow-card__content tn-margin-top">{{ item.content || item.remark || $tr('暂无处理内容') }}</view>
<view v-if="item.attachments && item.attachments.length" class="flow-attachments tn-margin-top">
<image
@@ -316,7 +316,7 @@
</view>
<view v-if="transitionOptions.length" class="flow-actions">
<view class="block-title">{{ t('flowActionTitle') }}</view>
<view class="block-title">{{ $tr('可执行操作') }}</view>
<view class="flow-action-list tn-margin-top">
<view
v-for="(item, index) in transitionOptions"
@@ -324,14 +324,14 @@
class="flow-action-btn"
@click="startTransitAction(item, getCurrentFlowItem())"
>
{{ item.nextStatusDesc || t('continueProcess') }}
{{ item.nextStatusDesc || $tr('继续处理') }}
</view>
</view>
</view>
<view v-if="canFixOnhold(currentFlowOrder)" class="flow-actions tn-margin-top">
<view class="flow-action-btn flow-action-btn--ghost" @click="startFixOnhold(currentFlowOrder)">
{{ t('supplementAction') }}
{{ $tr('补充信息') }}
</view>
</view>
</scroll-view>
@@ -455,158 +455,6 @@ export default {
components: {
RoomTypeSelector
},
i18n: {
zh: {
areaLabel: '所属区域',
assigneeLabel: '处理目标',
attachmentsLabel: '附件图片',
cancelProcess: '退出处理',
cancelSupplement: '取消补充',
changeRoomTypeLabel: '意向房型',
cleaningTimeLabel: '预约清洁时间',
contentLabel: '申请内容',
currentFlowTag: '当前节点',
currentStayInfo: '当前入住信息',
currentStayOrder: '当前入住订单',
emptyHistoryDesc: '当前类型还没有工单记录。',
emptyHistoryTitle: '暂无工单记录',
flowActionTitle: '可执行操作',
historyTab: '记录查询',
leaseLabel: '租期',
loadMore: '加载更多',
loadingMore: '加载中...',
loadOrderFailed: '入住信息加载失败',
noFlowContent: '暂无处理内容',
noMore: '没有更多了',
refresh: '刷新',
refreshing: '刷新中...',
remarkLabel: '补充说明',
remarkPlaceholder: '请输入补充说明,帮助工作人员更快处理',
roomLabel: '当前房间',
roomTypeLabel: '当前房型',
searchPlaceholder: '搜索工单标题或内容',
selectAssignee: '请选择处理目标',
selectDate: '请选择日期',
selectTime: '请选择时间',
submitSectionDefaultDesc: '以下内容将通过工单接口提交并进入后续流转。',
submitTab: '提交申请',
submitTicket: '提交工单',
submitting: '提交中...',
supplementAction: '补充信息',
supplementLabel: '补充业务信息',
supplementPlaceholder: '请输入{label}',
ticketKicker: 'WORK ORDER',
uploadImage: '上传图片',
uploadImageCountExceeded: '最多上传 6 张图片',
uploadImageFailed: '图片上传失败,请重试',
uploadImageOversize: '图片不能超过 5MB',
uploadTip: '支持上传 JPG、PNG 等图片,单张不超过 5MB,最多 6 张。',
uploadTipRepair: '支持上传 JPG、PNG 等图片,单张不超过 5MB,最多 6 张。报修至少上传 1 张图片。',
checkoutTimeLabel: '预计退宿时间',
renewalTimeLabel: '续住至',
submittedAtLabel: '提交时间',
submitSuccess: '工单提交成功',
submitFailed: '工单提交失败',
confirmSubmitTitle: '确认提交',
confirmSubmitContent: '确认提交当前工单吗?',
missingStayContext: '当前缺少入住订单或房间信息,暂无法提交工单',
repairAttachmentRequired: '请上传报修附件图片',
changeAreaRequired: '请选择意向房型',
checkoutTimeRequired: '请选择退宿时间',
checkoutReasonRequired: '请填写退宿原因',
loadHistoryFailed: '工单记录加载失败',
loadFlowsFailed: '工单流转加载失败',
loadActionsFailed: '工单操作项加载失败',
continueProcess: '继续处理',
loadAssigneeFailed: '处理目标加载失败',
submitSectionActionDesc: '当前工单正在处理中,提交后会继续流转。',
submitSectionSupplementDesc: '当前工单处于挂起状态,补充信息后会继续流转。',
currentStatusPending: '待处理',
currentStatusProcessing: '处理中',
currentStatusResolved: '已解决',
currentStatusClosed: '已结束',
allStatus: '全部',
pendingStatus: '待处理',
processingStatus: '处理中',
resolvedStatus: '已解决',
closedStatus: '已结束'
},
en: {
areaLabel: 'Area',
assigneeLabel: 'Assignee',
attachmentsLabel: 'Attachments',
cancelProcess: 'Cancel Action',
cancelSupplement: 'Cancel Supplement',
changeRoomTypeLabel: 'Preferred Room Type',
cleaningTimeLabel: 'Cleaning Time',
contentLabel: 'Content',
currentFlowTag: 'Current',
currentStayInfo: 'Current Stay',
currentStayOrder: 'Current Stay Order',
emptyHistoryDesc: 'No tickets of this type yet.',
emptyHistoryTitle: 'No Ticket Records',
flowActionTitle: 'Available Actions',
historyTab: 'History',
leaseLabel: 'Lease',
loadMore: 'Load More',
loadingMore: 'Loading...',
loadOrderFailed: 'Failed to load stay context',
noFlowContent: 'No handling content',
noMore: 'No more records',
refresh: 'Refresh',
refreshing: 'Refreshing...',
remarkLabel: 'Notes',
remarkPlaceholder: 'Enter notes to help the staff handle this ticket',
roomLabel: 'Room',
roomTypeLabel: 'Room Type',
searchPlaceholder: 'Search title or content',
selectAssignee: 'Select assignee',
selectDate: 'Select date',
selectTime: 'Select time',
submitSectionDefaultDesc: 'The form below will be submitted through the ticket APIs.',
submitTab: 'Submit',
submitTicket: 'Submit Ticket',
submitting: 'Submitting...',
supplementAction: 'Supplement',
supplementLabel: 'Supplementary Fields',
supplementPlaceholder: 'Please enter {label}',
ticketKicker: 'WORK ORDER',
uploadImage: 'Upload Image',
uploadImageCountExceeded: 'Up to 6 images',
uploadImageFailed: 'Failed to upload image',
uploadImageOversize: 'Image must be less than 5MB',
uploadTip: 'Upload JPG or PNG images, up to 6 images and 5MB each.',
uploadTipRepair: 'Upload JPG or PNG images, up to 6 images and 5MB each. Repair requires at least 1 image.',
checkoutTimeLabel: 'Checkout Time',
renewalTimeLabel: 'Renew Until',
submittedAtLabel: 'Submitted At',
submitSuccess: 'Ticket submitted',
submitFailed: 'Failed to submit ticket',
confirmSubmitTitle: 'Confirm',
confirmSubmitContent: 'Confirm submitting this ticket?',
missingStayContext: 'Missing current stay order or room information',
repairAttachmentRequired: 'Please upload repair images',
changeAreaRequired: 'Please select a room type',
checkoutTimeRequired: 'Please select checkout time',
checkoutReasonRequired: 'Please fill in the checkout reason',
loadHistoryFailed: 'Failed to load ticket history',
loadFlowsFailed: 'Failed to load ticket flows',
loadActionsFailed: 'Failed to load ticket actions',
continueProcess: 'Continue',
loadAssigneeFailed: 'Failed to load assignees',
submitSectionActionDesc: 'The ticket is in progress and will continue after submission.',
submitSectionSupplementDesc: 'The ticket is on hold and will continue after supplementing the information.',
currentStatusPending: 'Pending',
currentStatusProcessing: 'Processing',
currentStatusResolved: 'Resolved',
currentStatusClosed: 'Closed',
allStatus: 'All',
pendingStatus: 'Pending',
processingStatus: 'Processing',
resolvedStatus: 'Resolved',
closedStatus: 'Closed'
}
},
data() {
return {
serviceType: 'TicketRepairApply',
@@ -737,11 +585,11 @@ export default {
},
currentOrderStatusText() {
const status = Number(this.currentOrderDetail.orderStatus)
if (Number.isNaN(status)) return this.t('currentStayOrder')
if ([0, 1, 2].includes(status)) return this.t('currentStatusPending')
if ([3, 4, 7].includes(status)) return this.t('currentStatusProcessing')
if ([5, 6].includes(status)) return this.t('currentStatusResolved')
return this.t('currentStatusClosed')
if (Number.isNaN(status)) return this.$tr('当前入住订单')
if ([0, 1, 2].includes(status)) return this.$tr('待处理')
if ([3, 4, 7].includes(status)) return this.$tr('处理中')
if ([5, 6].includes(status)) return this.$tr('已解决')
return this.$tr('已结束')
},
contentFieldLabel() {
if (this.isChangeService) return this.language === 'en' ? 'Change Reason' : '调宿说明'
@@ -776,7 +624,7 @@ export default {
}
},
uploadTipText() {
return this.isRepairService ? this.t('uploadTipRepair') : this.t('uploadTip')
return this.isRepairService ? this.$tr('支持上传 JPG、PNG 等图片,单张不超过 5MB,最多 6 张。报修至少上传 1 张图片。') : this.$tr('支持上传 JPG、PNG 等图片,单张不超过 5MB,最多 6 张。')
},
submitButtonText() {
if (this.fixOnholdMode) {
@@ -785,9 +633,9 @@ export default {
if (this.transitActionMode) {
return this.transitActionOption && this.transitActionOption.nextStatusDesc
? this.transitActionOption.nextStatusDesc
: this.t('continueProcess')
: this.$tr('继续处理')
}
return this.t('submitTicket')
return this.$tr('提交工单')
},
submitSectionTitle() {
if (this.fixOnholdMode) return this.language === 'en' ? 'Supplement Information' : '补充工单信息'
@@ -795,9 +643,9 @@ export default {
return this.pageTitle
},
submitSectionDesc() {
if (this.fixOnholdMode) return this.t('submitSectionSupplementDesc')
if (this.transitActionMode) return this.t('submitSectionActionDesc')
return this.t('submitSectionDefaultDesc')
if (this.fixOnholdMode) return this.$tr('当前工单处于挂起状态,补充信息后会继续流转。')
if (this.transitActionMode) return this.$tr('当前工单正在处理中,提交后会继续流转。')
return this.$tr('以下内容将通过工单接口提交并进入后续流转。')
},
modeBannerTitle() {
if (this.fixOnholdMode) return this.language === 'en' ? 'Supplement Required' : '当前工单需要补充信息'
@@ -808,12 +656,12 @@ export default {
if (this.fixOnholdMode) {
return this.fixOnholdTicket && this.fixOnholdTicket.no
? `${this.fixOnholdTicket.no} ${this.language === 'en' ? 'needs more information before continuing.' : '需要补充信息后继续流转。'}`
: this.t('submitSectionSupplementDesc')
: this.$tr('当前工单处于挂起状态,补充信息后会继续流转。')
}
if (this.transitActionMode) {
return this.transitActionOption && this.transitActionOption.nextStatusDesc
? `${this.language === 'en' ? 'Current action:' : '当前操作:'}${this.transitActionOption.nextStatusDesc}`
: this.t('submitSectionActionDesc')
: this.$tr('当前工单正在处理中,提交后会继续流转。')
}
return ''
},
@@ -827,11 +675,11 @@ export default {
},
historyStatusOptions() {
return [
{ value: '', label: this.t('allStatus') },
{ value: '0', label: this.t('pendingStatus') },
{ value: '3', label: this.t('processingStatus') },
{ value: '5', label: this.t('resolvedStatus') },
{ value: '9', label: this.t('closedStatus') }
{ value: '', label: this.$tr('全部') },
{ value: '0', label: this.$tr('待处理') },
{ value: '3', label: this.$tr('处理中') },
{ value: '5', label: this.$tr('已解决') },
{ value: '9', label: this.$tr('已结束') }
]
},
transitAssigneePickerRange() {
@@ -868,9 +716,6 @@ export default {
this.refreshContext()
},
methods: {
t(key, params) {
return this.$translate(this.i18n, key, params)
},
handleScroll(e) {
this.scrollTop = e.detail.scrollTop
},
@@ -905,7 +750,7 @@ export default {
}
})
.catch(() => {
uni.showToast({ title: this.t('loadOrderFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('入住信息加载失败'), icon: 'none' })
})
},
resetForm() {
@@ -1005,28 +850,28 @@ export default {
},
getSubmitValidationMessage() {
if (this.fixOnholdMode && !this.fixOnholdFlowNo) {
return this.t('submitFailed')
return this.$tr('工单提交失败')
}
if (this.transitActionMode && !this.transitActionFlowNo) {
return this.t('submitFailed')
return this.$tr('工单提交失败')
}
if (!this.fixOnholdMode && !this.transitActionMode && !this.getSubmitOrderNo() && !this.getSubmitRoomCode()) {
return this.t('missingStayContext')
return this.$tr('当前缺少入住订单或房间信息,暂无法提交工单')
}
if (this.isRepairService && !(Array.isArray(this.form.attachments) && this.form.attachments.length)) {
return this.t('repairAttachmentRequired')
return this.$tr('请上传报修附件图片')
}
if (this.isChangeService && !this.switchForm.roomTypeCode) {
return this.t('changeAreaRequired')
return this.$tr('请选择意向房型')
}
if (this.isCheckOutService && !this.resolveCheckOutTime()) {
return this.t('checkoutTimeRequired')
return this.$tr('请选择退宿时间')
}
if (this.isCheckOutService && !String(this.form.content || '').trim()) {
return this.t('checkoutReasonRequired')
return this.$tr('请填写退宿原因')
}
if (this.showTransitAssigneeSelector && !this.transitSelectedAssigneeValue) {
return this.t('selectAssignee')
return this.$tr('请选择处理目标')
}
return ''
},
@@ -1278,8 +1123,8 @@ export default {
new Promise((resolve) => {
uni.showModal({
title: this.t('confirmSubmitTitle'),
content: this.t('confirmSubmitContent'),
title: this.$tr('确认提交'),
content: this.$tr('确认提交当前工单吗?'),
success: (res) => resolve(!!res.confirm),
fail: () => resolve(false)
})
@@ -1299,7 +1144,7 @@ export default {
return this.submitWithCompatibilityFallback(api, this.buildSubmitPayload())
})
.then(() => {
uni.showToast({ title: this.t('submitSuccess'), icon: 'success' })
uni.showToast({ title: this.$tr('工单提交成功'), icon: 'success' })
this.cancelFixOnhold()
this.cancelTransitAction()
this.resetForm()
@@ -1311,7 +1156,7 @@ export default {
return
}
uni.showToast({
title: this.getSubmitErrorText(error) || this.t('submitFailed'),
title: this.getSubmitErrorText(error) || this.$tr('工单提交失败'),
icon: 'none'
})
})
@@ -1360,7 +1205,7 @@ export default {
this.historyList = []
}
this.hasNext = false
uni.showToast({ title: this.t('loadHistoryFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('工单记录加载失败'), icon: 'none' })
})
.finally(() => {
this.historyLoading = false
@@ -1380,10 +1225,10 @@ export default {
return 'closed'
},
statusText(status) {
if ([0, 1, 2].includes(status)) return this.t('pendingStatus')
if ([3, 4, 7].includes(status)) return this.t('processingStatus')
if ([5, 6].includes(status)) return this.t('resolvedStatus')
return this.t('closedStatus')
if ([0, 1, 2].includes(status)) return this.$tr('待处理')
if ([3, 4, 7].includes(status)) return this.$tr('处理中')
if ([5, 6].includes(status)) return this.$tr('已解决')
return this.$tr('已结束')
},
openFlows(item) {
this.currentFlowOrder = item
@@ -1398,7 +1243,7 @@ export default {
return this.loadTransitionOptions(this.getCurrentFlowItem())
})
.catch(() => {
uni.showToast({ title: this.t('loadFlowsFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('工单流转加载失败'), icon: 'none' })
})
.finally(() => {
this.flowLoading = false
@@ -1419,7 +1264,7 @@ export default {
})
.catch(() => {
this.transitionOptions = []
uni.showToast({ title: this.t('loadActionsFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('工单操作项加载失败'), icon: 'none' })
return []
})
},
@@ -1624,7 +1469,7 @@ export default {
this.transitAssigneeGroups = this.normalizeTransitAssigneeGroups(response)
})
.catch(() => {
uni.showToast({ title: this.t('loadAssigneeFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('处理目标加载失败'), icon: 'none' })
})
},
onTransitAssigneeChange(event) {
@@ -1671,13 +1516,13 @@ export default {
this.form.attachments.splice(index, 1)
},
onUploadError() {
uni.showToast({ title: this.t('uploadImageFailed'), icon: 'none' })
uni.showToast({ title: this.$tr('图片上传失败,请重试'), icon: 'none' })
},
onUploadOversize() {
uni.showToast({ title: this.t('uploadImageOversize'), icon: 'none' })
uni.showToast({ title: this.$tr('图片不能超过 5MB'), icon: 'none' })
},
onUploadExceed() {
uni.showToast({ title: this.t('uploadImageCountExceeded'), icon: 'none' })
uni.showToast({ title: this.$tr('最多上传 6 张图片'), icon: 'none' })
},
getAttachmentPreview(attachment) {
return addFilePrefix(pickReadableValue(attachment && attachment.resourceUrl, attachment && attachment.url, attachment && attachment.path))