liujie
2026-09-14 15defa991fcd30b9fa60bab17d2230b5929bf2a2
mingdaojingjiang_guide_app/pages/workbench/index.vue
@@ -48,7 +48,7 @@
            </template>
          </view>
          <view class="receiving-right">
            <view>{{ receivingMeetingPoint }}</view>
            <view class="meeting-point-name">{{ receivingMeetingPoint }}</view>
            <view class="meeting-link" @tap="viewMeetingPoint">查看汇合点</view>
          </view>
        </view>
@@ -243,7 +243,12 @@
    meetingPointLongitude: meetingPoint.longitude ?? fallback.meetingPointLongitude ?? fallback.longitude,
    latitude: meetingPoint.latitude ?? fallback.latitude,
    longitude: meetingPoint.longitude ?? fallback.longitude,
    serviceStartAt: session.serviceStartAt || fallback.serviceStartAt || ''
    receivingMode: session.receivingMode || fallback.receivingMode || '',
    serviceStartAt: session.serviceStartAt || fallback.serviceStartAt || '',
    firstOrderLeadMinutes: resolvePositiveMinutes(
      scenic.firstOrderLeadMinutes ?? fallback.firstOrderLeadMinutes,
      15
    )
  }
}
@@ -252,6 +257,11 @@
    return NaN
  }
  return new Date(String(value).trim().replace(' ', 'T')).getTime()
}
function resolvePositiveMinutes(value, fallback = 15) {
  const minutes = Number(value)
  return Number.isFinite(minutes) && minutes > 0 ? minutes : fallback
}
export default {
@@ -275,6 +285,7 @@
      unreadMessageCount: 0,
      unreadMessageInitialized: false,
      countdownSeconds: 0,
      countdownFallbackEndAt: null,
      countdownTimer: null,
      refreshTimer: null,
      refreshing: false,
@@ -561,13 +572,33 @@
      const order = this.activeReceivingOrder
      const serving = this.isServing
      const durationMinutes = Number(order.durationMinutes || 30)
      const startAt = parseApiDateTime(serving
        ? order.lectureStartTime
        : this.guide.receivingConfig && this.guide.receivingConfig.serviceStartAt)
      const receivingConfig = this.guide.receivingConfig || {}
      const leadMinutes = resolvePositiveMinutes(receivingConfig.firstOrderLeadMinutes, 15)
      const receiveStartAt = parseApiDateTime(
        order.receiveStartTime || order.receiveTime || order.acceptedAt
      )
      const configuredStartAt = parseApiDateTime(receivingConfig.serviceStartAt)
      let startAt = parseApiDateTime(serving ? order.lectureStartTime : receivingConfig.serviceStartAt)
      if (!serving && receivingConfig.receivingMode === 'PRIVATE'
          && Number.isFinite(receiveStartAt)
          && (!Number.isFinite(configuredStartAt) || configuredStartAt <= receiveStartAt)) {
        startAt = receiveStartAt + leadMinutes * 60 * 1000
      }
      if (!Number.isFinite(startAt)) {
        this.countdownSeconds = 0
        if (serving) {
          this.countdownSeconds = 0
          return
        }
        if (!Number.isFinite(this.countdownFallbackEndAt)) {
          this.countdownFallbackEndAt = Date.now() + leadMinutes * 60 * 1000
        }
        this.countdownSeconds = Math.max(
          0,
          Math.ceil((this.countdownFallbackEndAt - Date.now()) / 1000)
        )
        return
      }
      this.countdownFallbackEndAt = null
      const endAt = serving ? startAt + durationMinutes * 60 * 1000 : startAt
      this.countdownSeconds = Math.max(0, Math.ceil((endAt - Date.now()) / 1000))
    },
@@ -576,6 +607,7 @@
        clearInterval(this.countdownTimer)
        this.countdownTimer = null
      }
      this.countdownFallbackEndAt = null
    },
    finishLectureWhenCountdownEnds() {
      if (!this.isServing || this.finishingLecture) {
@@ -876,9 +908,10 @@
}
.receiving-summary {
  display: flex;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 24rpx;
  align-items: center;
  justify-content: space-between;
  height: 160rpx;
  padding: 0 58rpx;
  border-bottom: 1rpx solid #d8d8d8;
@@ -891,6 +924,7 @@
}
.receiving-left {
  min-width: 0;
  color: #1f2937;
  font-size: 30rpx;
  font-weight: 500;
@@ -898,26 +932,61 @@
.service-line {
  display: flex;
  align-items: center;
  gap: 16rpx;
  min-width: 0;
  overflow: hidden;
  color: #1f2937;
  font-size: 29rpx;
  line-height: 1.3;
  white-space: nowrap;
}
.service-line > text:first-child {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.service-line > text:last-child {
  flex-shrink: 0;
  white-space: nowrap;
}
.start-line {
  min-width: 0;
  margin-top: 34rpx;
  overflow: hidden;
  color: #1f2937;
  font-size: 29rpx;
  line-height: 1.3;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.receiving-right {
  min-width: 0;
  overflow: hidden;
  color: #111827;
  text-align: right;
  font-size: 25rpx;
  line-height: 1.8;
}
.meeting-point-name,
.meeting-link {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.meeting-point-name {
  color: #111827;
}
.meeting-link {
  color: #1685ff;
}