| | |
| | | const router = useRouter() |
| | | const appointmentAssetBase = '/static/appointment' |
| | | const defaultPlateTag = '新能源' |
| | | const VISIT_REASON_CODE_OTHER = 'OTHER' |
| | | const VISIT_REASON_NAME_OTHER = '其他' |
| | | const VISIT_TIME_MODE_SINGLE = 'SINGLE' |
| | | const VISIT_TIME_MODE_MULTI = 'MULTI' |
| | | const APPROVAL_RESULT_SUBSCRIBE_TEMPLATE_ID = '4FQovCBNFM7rth42AWHTusHajO788eT9VpplSN4ZG2s' |
| | | const APPROVAL_RESULT_SUBSCRIBE_TEMPLATE_ID = 'rIJpfN51_q818RTpJAqTe5ssTwWCHnxDM5rpq64uuKM' |
| | | const TIME_SLOT_LABEL_TO_CODE = { |
| | | '全天00:00-23:59': 'ALL_DAY', |
| | | '上午00:00-11:59': 'AM', |
| | |
| | | const isVisitReasonRequired = computed(() => isFieldRequired(APPOINTMENT_FIELD_CODES.VISIT_REASON, true)) |
| | | const isRespondentRequired = computed(() => isFieldRequired(APPOINTMENT_FIELD_CODES.RESPONDENT, true)) |
| | | const isVisitTimeRequired = computed(() => isFieldRequired(APPOINTMENT_FIELD_CODES.VISIT_START_TIME, true)) |
| | | const showCustomReasonInput = computed(() => { |
| | | if (!selectedVisitReason.value) { |
| | | return false |
| | | } |
| | | return selectedVisitReason.value.reasonCode === VISIT_REASON_CODE_OTHER |
| | | || selectedVisitReason.value.reasonName === VISIT_REASON_NAME_OTHER |
| | | }) |
| | | const showCustomReasonInput = computed(() => Boolean(selectedVisitReason.value)) |
| | | const showReasonPicker = ref(false) |
| | | const appointmentIcons = { |
| | | male: `${appointmentAssetBase}/man.png`, |
| | |
| | | } |
| | | } |
| | | |
| | | function sortVisitReasons(reasons: MiniVisitReasonItem[]) { |
| | | return [...reasons].sort((left, right) => { |
| | | const leftIsOther = left.reasonCode === 'OTHER' || left.reasonName === '其他' |
| | | const rightIsOther = right.reasonCode === 'OTHER' || right.reasonName === '其他' |
| | | if (leftIsOther !== rightIsOther) { |
| | | return leftIsOther ? 1 : -1 |
| | | } |
| | | |
| | | const leftOrder = left.sortOrder ?? Number.MAX_SAFE_INTEGER |
| | | const rightOrder = right.sortOrder ?? Number.MAX_SAFE_INTEGER |
| | | if (leftOrder !== rightOrder) { |
| | | return leftOrder - rightOrder |
| | | } |
| | | return left.id - right.id |
| | | }) |
| | | } |
| | | |
| | | async function loadVisitReasons() { |
| | | try { |
| | | visitReasons.value = await fetchVisitReasons() |
| | | visitReasons.value = sortVisitReasons(await fetchVisitReasons()) |
| | | if (selectedVisitReason.value) { |
| | | const nextReason = visitReasons.value.find(item => item.reasonCode === selectedVisitReason.value?.reasonCode) || null |
| | | selectedVisitReason.value = nextReason |
| | |
| | | const target = visitReasons.value.find(item => item.reasonName === reasonName) || null |
| | | selectedVisitReason.value = target |
| | | formData.reason = target?.reasonName || '' |
| | | if (!showCustomReasonInput.value) { |
| | | customVisitReason.value = '' |
| | | } |
| | | } |
| | | |
| | | function resolveVisitTimeMode() { |
| | |
| | | } |
| | | } |
| | | |
| | | async function prefillDefaultVisitorForCreate() { |
| | | if (rebookOrderId.value || rebookOrderUuid.value || formData.visitors.length > 0) { |
| | | return |
| | | } |
| | | try { |
| | | const visitors = await fetchMyVisitors() |
| | | const defaultVisitor = visitors.find(item => item.isDefault) |
| | | if (!defaultVisitor) { |
| | | return |
| | | } |
| | | if (defaultVisitor.missingFieldCodes?.length) { |
| | | uni.showToast({ |
| | | title: '默认来访人信息不完善,请先完善后再预约', |
| | | icon: 'none', |
| | | duration: 3000, |
| | | }) |
| | | return |
| | | } |
| | | formData.visitors = [mapVisitorFromCurrentList(defaultVisitor)] |
| | | } |
| | | catch (error) { |
| | | console.warn('prefill default visitor failed', error) |
| | | } |
| | | } |
| | | |
| | | async function applyRebookPrefill(detailData: MiniMyAppointmentDetailItem, currentVisitors: MiniVisitorListItem[]) { |
| | | const warnings: string[] = [] |
| | | resetForm() |
| | |
| | | warnings.push('原拜访事由不可用,请重新选择') |
| | | } |
| | | } |
| | | customVisitReason.value = detailData.visitReasonCode === VISIT_REASON_CODE_OTHER |
| | | ? detailData.visitReasonOther || '' |
| | | : '' |
| | | customVisitReason.value = detailData.visitReasonOther || '' |
| | | |
| | | const currentVisitorMap = new Map(currentVisitors.map(item => [item.id, item])) |
| | | const restoredVisitors: AppointmentVisitor[] = [] |
| | |
| | | if (!visitReasonCode) { |
| | | throw new Error('请选择拜访事由') |
| | | } |
| | | if (visitReasonCode === VISIT_REASON_CODE_OTHER && !customVisitReason.value.trim()) { |
| | | throw new Error('请输入具体来访事由') |
| | | const visitReasonOther = customVisitReason.value.trim() |
| | | if (!visitReasonOther) { |
| | | throw new Error('请输入事由说明') |
| | | } |
| | | if (visitReasonCode === VISIT_REASON_CODE_OTHER && customVisitReason.value.trim().length > 15) { |
| | | throw new Error('具体来访事由不能超过15个字') |
| | | if (visitReasonOther.length > 15) { |
| | | throw new Error('事由说明不能超过15个字') |
| | | } |
| | | if (!formData.visitors.length) { |
| | | throw new Error('请选择来访人员') |
| | |
| | | const payload: MiniAppointmentCreateRequest = { |
| | | visitedUserId: visitedUser.id, |
| | | visitReasonCode, |
| | | visitReasonOther, |
| | | visitTimeMode, |
| | | personEntry: true, |
| | | visitorIds: formData.visitors.map(item => item.id), |
| | | vehicleEntry: formData.vehicleEntry, |
| | | } |
| | | if (visitReasonCode === VISIT_REASON_CODE_OTHER) { |
| | | payload.visitReasonOther = customVisitReason.value.trim() |
| | | } |
| | | |
| | | if (visitTimeMode === VISIT_TIME_MODE_SINGLE) { |
| | | if (!formData.visitTimeSingle) { |
| | | throw new Error('请选择拜访时间') |
| | |
| | | loadFieldConfigs(), |
| | | loadBookingSettings(), |
| | | loadVisitReasons(), |
| | | ]).then(() => prefillFromRebookDetail()) |
| | | ]).then(async () => { |
| | | if (rebookOrderId.value && rebookOrderUuid.value) { |
| | | await prefillFromRebookDetail() |
| | | return |
| | | } |
| | | await prefillDefaultVisitorForCreate() |
| | | }) |
| | | }) |
| | | |
| | | onUnload(() => { |
| | |
| | | class="mb-[48rpx] rounded-[16rpx] bg-white pl-[32rpx] pr-[12rpx] py-[8rpx] shadow-[0px_4px_8px_0px_rgba(6,47,108,0.1608)]"> |
| | | <wd-form :model="formData"> |
| | | <!-- 被访人 --> |
| | | <wd-input v-model="formData.interviewee" placeholder="请输入要接见谁" align="right" custom-class="custom-cell" |
| | | <wd-input v-model="formData.interviewee" placeholder="请输入要拜访谁" align="right" custom-class="custom-cell" |
| | | placeholder-class="custom-placeholder"> |
| | | <template #label> |
| | | <view class="inline-flex items-start"> |
| | |
| | | v-model.trim="customVisitReason" |
| | | class="min-h-[160rpx] w-full rounded-[16rpx] bg-[#F8FAFD] px-[24rpx] py-[20rpx] text-[26rpx] text-[#333333] box-border" |
| | | maxlength="15" |
| | | placeholder="请输入具体来访事由" |
| | | placeholder="请输入事由说明" |
| | | placeholder-class="text-[#B3B3B3]" |
| | | /> |
| | | </view> |
| | |
| | | class="visitor-row flex items-center justify-between px-[8rpx] py-[20rpx]" |
| | | > |
| | | <view class="flex items-center min-w-0 flex-1"> |
| | | <text class="w-[72rpx] shrink-0 text-[28rpx] text-[#333333]"> |
| | | <text class="w-[96rpx] shrink-0 truncate text-[28rpx] text-[#333333]"> |
| | | {{ visitor.name }} |
| | | </text> |
| | | <view class="ml-[20rpx] min-w-0 flex-1"> |
| | | <view class="ml-[12rpx] min-w-0 flex-1"> |
| | | <view class="flex items-center min-w-0"> |
| | | <image :src="getVisitorGenderIcon(visitor.gender)" class="h-[32rpx] w-[32rpx] shrink-0" /> |
| | | <text class="ml-[10rpx] truncate text-[24rpx] text-[#999999]"> |
| | |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view class="ml-[16rpx] flex items-center shrink-0"> |
| | | <view class="ml-[8rpx] flex items-center shrink-0"> |
| | | <view |
| | | v-if="visitor.badge" |
| | | class="rounded-full border border-[#1677FF] border-solid px-[20rpx] py-[8rpx] text-[24rpx] text-[#1677FF]" |
| | | class="rounded-full border border-[#1677FF] border-solid px-[16rpx] py-[8rpx] text-[24rpx] text-[#1677FF]" |
| | | > |
| | | {{ visitor.badge }} |
| | | </view> |