Files
medical-mall/pages/mall/delivery/orders/exception.uvue

167 lines
4.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<ServicePageScaffold title="异常上报" fallback-url="/pages/mall/delivery/orders/detail">
<ServicePanel title="异常类型" subtitle="高风险异常需立即提醒联系家属、调度或 120。">
<view class="type-grid">
<view v-for="item in exceptionTypes" :key="item.value" class="type-item" :class="currentType == item.value ? 'type-active' : ''" @click="currentType = item.value">
<text class="type-text">{{ item.label }}</text>
</view>
</view>
</ServicePanel>
<ServicePanel title="异常说明" subtitle="说明必填,支持上传图片凭证。">
<textarea class="textarea" v-model="description" placeholder="请填写异常发生情况、现场处置动作和需要协同的事项"></textarea>
<button class="secondary-btn" @click="chooseImage">上传异常图片</button>
<text class="info-text">已选择图片:{{ images.length }} 张</text>
<text v-if="isHighRisk" class="risk-text">高风险异常:请同步联系家属/调度/120并保留处置留痕。</text>
</ServicePanel>
<button class="primary-btn" :disabled="submitting" @click="submitForm">{{ submitting ? '提交中...' : '提交异常' }}</button>
</ServicePageScaffold>
</template>
<script setup lang="uts">
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import ServicePageScaffold from '@/components/homeService/ServicePageScaffold.uvue'
import ServicePanel from '@/components/homeService/ServicePanel.uvue'
import { submitException } from '@/services/deliveryService.uts'
import { requireDeliveryAuth } from '@/utils/deliveryAuth.uts'
import { getDeliveryRouteParam } from '@/utils/deliveryRoute.uts'
const orderId = ref('')
const currentType = ref('cannot_contact_elder')
const description = ref('')
const images = ref([] as Array<string>)
const submitting = ref(false)
const exceptionTypes = [
{ label: '无法联系老人', value: 'cannot_contact_elder' },
{ label: '无法入户', value: 'cannot_enter_home' },
{ label: '地址错误', value: 'wrong_address' },
{ label: '老人拒绝服务', value: 'elder_refuse_service' },
{ label: '家属要求改期', value: 'family_requests_reschedule' },
{ label: '现场存在安全风险', value: 'safety_risk' },
{ label: '老人身体异常', value: 'elder_health_abnormal' },
{ label: '突发疾病', value: 'emergency_illness' },
{ label: '服务项目无法完成', value: 'item_unavailable' },
{ label: '其他', value: 'other' }
]
const isHighRisk = computed(() => currentType.value == 'safety_risk' || currentType.value == 'elder_health_abnormal' || currentType.value == 'emergency_illness')
function wrapChooseImage(): Promise<Array<string>> {
return new Promise((resolve, reject) => {
uni.chooseImage({
count: 3,
sourceType: ['camera', 'album'],
success: (res) => { resolve(res.tempFilePaths) },
fail: () => { reject(new Error('选择图片失败')) }
})
})
}
async function chooseImage() {
try {
images.value = await wrapChooseImage()
} catch (error) {
uni.showToast({ title: '图片选择失败', icon: 'none' })
}
}
async function submitForm() {
if (submitting.value) return
if (description.value.trim() == '') {
uni.showToast({ title: '异常说明不能为空', icon: 'none' })
return
}
submitting.value = true
try {
await submitException(orderId.value, { exceptionType: currentType.value as any, description: description.value.trim(), images: images.value })
uni.showToast({ title: '异常已上报', icon: 'success' })
uni.setStorageSync('delivery_orders_tab', 'exception')
uni.switchTab({ url: '/pages/mall/delivery/orders/index' })
} finally {
submitting.value = false
}
}
onLoad(async (options) => {
const authResult = await requireDeliveryAuth({ redirectOnFail: true, toastOnFail: true })
if (!authResult.ok) {
return
}
if (options != null) {
orderId.value = getDeliveryRouteParam(options as UTSJSONObject, 'id')
}
})
</script>
<style scoped>
.type-grid {
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.type-item {
width: 48%;
padding: 18rpx 16rpx;
margin-bottom: 16rpx;
border-radius: 18rpx;
background: #eef2f6;
}
.type-active {
background: #0f766e;
}
.type-text {
font-size: 24rpx;
line-height: 34rpx;
color: #476178;
}
.type-active .type-text {
color: #ffffff;
}
.textarea {
width: 100%;
min-height: 220rpx;
padding: 24rpx;
border-radius: 20rpx;
background: #f2f7f6;
font-size: 28rpx;
box-sizing: border-box;
}
.secondary-btn,
.primary-btn {
margin-top: 18rpx;
border-radius: 18rpx;
font-size: 28rpx;
}
.secondary-btn {
background: #eaf2f0;
color: #0f766e;
}
.primary-btn {
background: #0f766e;
color: #ffffff;
}
.info-text,
.risk-text {
display: block;
margin-top: 12rpx;
font-size: 24rpx;
line-height: 36rpx;
}
.info-text {
color: #5e758c;
}
.risk-text {
color: #b45309;
font-weight: 700;
}
</style>