|
|
|
@@ -61,6 +61,10 @@ |
|
|
|
<text v-if="returnTime" class="return-time">回寄时间:{{ returnTime }}</text> |
|
|
|
<text class="copy-return-no" @tap="copyReturnTrackingNo">复制单号</text> |
|
|
|
</view> |
|
|
|
<view v-if="sampleEditRejectReason" class="reject-info"> |
|
|
|
<text class="reject-title">修改申请未通过</text> |
|
|
|
<text class="reject-text">原因:{{ sampleEditRejectReason }}</text> |
|
|
|
</view> |
|
|
|
<view class="form-group"> |
|
|
|
<text class="form-label">送检样本类型{{ sampleRequired ? '' : '(选填)' }}</text> |
|
|
|
<u-checkbox-group v-model="form.sample_types" placement="row" :wrap="true" @change="onSampleTypesChange"> |
|
|
|
@@ -131,9 +135,24 @@ |
|
|
|
<text class="agree-text">请阅读并同意</text> |
|
|
|
<text class="agree-link" @tap.stop="openNotice">《患者告知书》</text> |
|
|
|
</view> |
|
|
|
<u-button :text="submitButtonText" :loading="submitting" @click="handleSubmit" color="#0E63E3" size="large" /> |
|
|
|
<u-button v-if="canApplySampleEdit" text="申请修改送检信息" :loading="applyEditSubmitting" @click="showApplyEditDialog" |
|
|
|
color="#0E63E3" plain size="large" /> |
|
|
|
<u-button v-if="!canApplySampleEdit" :text="submitButtonText" :loading="submitting" @click="handleSubmit" color="#0E63E3" size="large" /> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 修改申请弹窗 --> |
|
|
|
<u-popup :show="applyEditVisible" mode="center" round="12" :safeAreaInsetBottom="false" @close="applyEditVisible = false"> |
|
|
|
<view class="apply-popup"> |
|
|
|
<view class="apply-title">申请修改送检信息</view> |
|
|
|
<view class="apply-desc">请填写需要修改送检信息的原因,平台审核通过后即可重新编辑。</view> |
|
|
|
<textarea v-model="applyEditReason" class="apply-textarea" maxlength="500" placeholder="请输入申请原因" /> |
|
|
|
<view class="apply-actions"> |
|
|
|
<u-button text="取消" @click="applyEditVisible = false" plain color="#909399" /> |
|
|
|
<u-button text="提交申请" :loading="applyEditSubmitting" @click="submitApplyEdit" color="#0E63E3" /> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</u-popup> |
|
|
|
|
|
|
|
<!-- 地区选择器 --> |
|
|
|
<u-picker v-if="regionColumns[0].length" :show="showRegionPicker" :columns="regionColumns" @confirm="onRegionConfirm" |
|
|
|
@cancel="showRegionPicker = false" @change="onRegionChange" :defaultIndex="regionDefaultIndex" /> |
|
|
|
@@ -163,19 +182,33 @@ const submitting = ref(false) |
|
|
|
const agreed = ref(false) |
|
|
|
const sampleTypeList = ref([]) |
|
|
|
const sampleRequired = ref(false) |
|
|
|
const sampleReceiverInfo = ref({ address: '', receiver: '', phone: '' }) |
|
|
|
const sampleReceiverInfo = ref({ address: '', receiver: '', phone: '', contact_phone: '' }) |
|
|
|
const sampleInfoStatus = ref(0) |
|
|
|
const returnTrackingNo = ref('') |
|
|
|
const returnTime = ref('') |
|
|
|
const sampleEditReason = ref('') |
|
|
|
const sampleEditRejectReason = ref('') |
|
|
|
const sampleEditApplyTime = ref('') |
|
|
|
const applyEditVisible = ref(false) |
|
|
|
const applyEditReason = ref('') |
|
|
|
const applyEditSubmitting = ref(false) |
|
|
|
const sampleEditAuditTmplId = ref('') |
|
|
|
const isSampleReturned = computed(() => sampleInfoStatus.value === 2) |
|
|
|
const isSampleInfoLocked = computed(() => sampleInfoStatus.value === 1 || sampleInfoStatus.value === 2) |
|
|
|
const isSampleEditApplying = computed(() => sampleInfoStatus.value === 3) |
|
|
|
const isSampleInfoLocked = computed(() => sampleInfoStatus.value === 1 || sampleInfoStatus.value === 2 || sampleInfoStatus.value === 3) |
|
|
|
const canApplySampleEdit = computed(() => sampleInfoStatus.value === 1) |
|
|
|
const sampleInfoStatusText = computed(() => { |
|
|
|
if (sampleInfoStatus.value === 3) return '申请审核中' |
|
|
|
if (sampleInfoStatus.value === 2) return '已寄回' |
|
|
|
if (sampleInfoStatus.value === 1) return '已生效' |
|
|
|
return '' |
|
|
|
}) |
|
|
|
const sampleInfoStatusClass = computed(() => sampleInfoStatus.value === 2 ? 'returned' : 'effective') |
|
|
|
const sampleInfoStatusClass = computed(() => { |
|
|
|
if (sampleInfoStatus.value === 3) return 'applying' |
|
|
|
return sampleInfoStatus.value === 2 ? 'returned' : 'effective' |
|
|
|
}) |
|
|
|
const submitButtonText = computed(() => { |
|
|
|
if (sampleInfoStatus.value === 3) return '修改申请审核中' |
|
|
|
if (sampleInfoStatus.value === 2) return '样品已寄回' |
|
|
|
if (sampleInfoStatus.value === 1) return '送检信息已生效' |
|
|
|
return '提交送检信息' |
|
|
|
@@ -280,8 +313,34 @@ onLoad(async () => { |
|
|
|
await loadRegions() |
|
|
|
await loadPatientInfo() |
|
|
|
await loadSampleTypes() |
|
|
|
await loadSubscribeConfig() |
|
|
|
}) |
|
|
|
|
|
|
|
const loadSubscribeConfig = async () => { |
|
|
|
try { |
|
|
|
const res = await get('/api/mp/subscribeConfig') |
|
|
|
if (res.data && res.data.sample_edit_audit) { |
|
|
|
sampleEditAuditTmplId.value = res.data.sample_edit_audit |
|
|
|
} |
|
|
|
} catch (e) {} |
|
|
|
} |
|
|
|
|
|
|
|
const requestSampleEditSubscribe = () => { |
|
|
|
return new Promise((resolve) => { |
|
|
|
if (!sampleEditAuditTmplId.value) return resolve(false) |
|
|
|
// #ifdef MP-WEIXIN |
|
|
|
wx.requestSubscribeMessage({ |
|
|
|
tmplIds: [sampleEditAuditTmplId.value], |
|
|
|
success: () => resolve(true), |
|
|
|
fail: () => resolve(false) |
|
|
|
}) |
|
|
|
// #endif |
|
|
|
// #ifndef MP-WEIXIN |
|
|
|
resolve(false) |
|
|
|
// #endif |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
const loadPatientInfo = async () => { |
|
|
|
try { |
|
|
|
const res = await get('/api/mp/sampleInfo') |
|
|
|
@@ -302,8 +361,11 @@ const loadPatientInfo = async () => { |
|
|
|
sampleInfoStatus.value = Number(res.data.sample_info_status) || 0 |
|
|
|
returnTrackingNo.value = res.data.return_tracking_no || '' |
|
|
|
returnTime.value = res.data.return_time || '' |
|
|
|
sampleReceiverInfo.value = res.data.sample_receiver_info || { address: '', receiver: '', phone: '' } |
|
|
|
if (sampleInfoStatus.value === 1) { |
|
|
|
sampleEditReason.value = res.data.sample_edit_reason || '' |
|
|
|
sampleEditRejectReason.value = res.data.sample_edit_reject_reason || '' |
|
|
|
sampleEditApplyTime.value = res.data.sample_edit_apply_time || '' |
|
|
|
sampleReceiverInfo.value = res.data.sample_receiver_info || { address: '', receiver: '', phone: '', contact_phone: '' } |
|
|
|
if ((sampleInfoStatus.value === 1 && !sampleEditRejectReason.value) || sampleInfoStatus.value === 3) { |
|
|
|
setTimeout(() => showLockedTip(), 300) |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -406,9 +468,18 @@ const contactPlatform = () => { |
|
|
|
} |
|
|
|
|
|
|
|
const showLockedTip = () => { |
|
|
|
if (isSampleEditApplying.value) { |
|
|
|
uni.showModal({ |
|
|
|
title: '温馨提示', |
|
|
|
content: '送检信息修改申请正在审核中,请等待平台处理。', |
|
|
|
showCancel: false, |
|
|
|
confirmText: '知道了' |
|
|
|
}) |
|
|
|
return |
|
|
|
} |
|
|
|
if (isSampleReturned.value) { |
|
|
|
uni.showModal({ |
|
|
|
title: '提示', |
|
|
|
title: '温馨提示', |
|
|
|
content: `样品已经寄回,回寄物流单号:${returnTrackingNo.value || '—'}。`, |
|
|
|
cancelText: '知道了', |
|
|
|
confirmText: '复制单号', |
|
|
|
@@ -419,26 +490,46 @@ const showLockedTip = () => { |
|
|
|
return |
|
|
|
} |
|
|
|
const phone = getContactPhone() |
|
|
|
if (!phone) { |
|
|
|
uni.showModal({ |
|
|
|
title: '提示', |
|
|
|
content: '送检信息已生效,如需修改请联系平台重置修改权限。', |
|
|
|
showCancel: false, |
|
|
|
confirmText: '知道了' |
|
|
|
}) |
|
|
|
return |
|
|
|
} |
|
|
|
let content = '送检信息已生效,如需修改请点击页面的【申请修改送检信息】按钮申请,通过后可重新提交送检信息。' |
|
|
|
if (phone) content += `详情咨询${phone}。` |
|
|
|
uni.showModal({ |
|
|
|
title: '提示', |
|
|
|
content: `送检信息已生效,如需修改请联系平台【${phone}】重置修改权限。`, |
|
|
|
cancelText: '知道了', |
|
|
|
confirmText: '联系平台', |
|
|
|
success: (res) => { |
|
|
|
if (res.confirm) contactPlatform() |
|
|
|
} |
|
|
|
title: '温馨提示', |
|
|
|
content, |
|
|
|
showCancel: false, |
|
|
|
confirmText: '知道了' |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
const showApplyEditDialog = () => { |
|
|
|
if (!canApplySampleEdit.value) return showLockedTip() |
|
|
|
applyEditReason.value = '' |
|
|
|
applyEditVisible.value = true |
|
|
|
} |
|
|
|
|
|
|
|
const submitApplyEdit = async () => { |
|
|
|
if (!applyEditReason.value.trim()) { |
|
|
|
return uni.showToast({ title: '请填写申请原因', icon: 'none' }) |
|
|
|
} |
|
|
|
applyEditSubmitting.value = true |
|
|
|
try { |
|
|
|
await requestSampleEditSubscribe() |
|
|
|
const params = { reason: applyEditReason.value.trim() } |
|
|
|
// #ifdef MP-WEIXIN |
|
|
|
params.mp_env_version = uni.getAccountInfoSync().miniProgram.envVersion || 'release' |
|
|
|
// #endif |
|
|
|
await post('/api/mp/applySampleInfoEdit', params) |
|
|
|
sampleInfoStatus.value = 3 |
|
|
|
sampleEditReason.value = applyEditReason.value.trim() |
|
|
|
sampleEditApplyTime.value = '' |
|
|
|
applyEditVisible.value = false |
|
|
|
uni.showToast({ title: '申请已提交', icon: 'success' }) |
|
|
|
} catch (e) { |
|
|
|
if (e && e.msg) uni.showToast({ title: e.msg, icon: 'none' }) |
|
|
|
} finally { |
|
|
|
applyEditSubmitting.value = false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const copyReturnTrackingNo = () => { |
|
|
|
if (!returnTrackingNo.value) return uni.showToast({ title: '暂无单号', icon: 'none' }) |
|
|
|
uni.setClipboardData({ |
|
|
|
@@ -494,10 +585,12 @@ const handleSubmit = async () => { |
|
|
|
uni.showToast({ title: '提交成功', icon: 'success' }) |
|
|
|
setTimeout(() => uni.navigateBack(), 1500) |
|
|
|
} catch (e) { |
|
|
|
if (e && e.data && [1, 2].includes(Number(e.data.sample_info_status))) { |
|
|
|
if (e && e.data && [1, 2, 3].includes(Number(e.data.sample_info_status))) { |
|
|
|
sampleInfoStatus.value = Number(e.data.sample_info_status) |
|
|
|
returnTrackingNo.value = e.data.return_tracking_no || returnTrackingNo.value |
|
|
|
returnTime.value = e.data.return_time || returnTime.value |
|
|
|
sampleEditReason.value = e.data.sample_edit_reason || sampleEditReason.value |
|
|
|
sampleEditApplyTime.value = e.data.sample_edit_apply_time || sampleEditApplyTime.value |
|
|
|
if (e.data.sample_receiver_info) sampleReceiverInfo.value = e.data.sample_receiver_info |
|
|
|
return showLockedTip() |
|
|
|
} |
|
|
|
@@ -512,7 +605,7 @@ const handleSubmit = async () => { |
|
|
|
.page { min-height: 100vh; background: #f4f4f5; padding: 24rpx; padding-bottom: 260rpx; } |
|
|
|
.section { background: #fff; border-radius: 10rpx; padding: 32rpx; margin-bottom: 24rpx; border: 1rpx solid #ebeef5; } |
|
|
|
.section-title { display: flex; align-items: center; gap: 12rpx; font-size: 32rpx; font-weight: 600; color: #333; margin-bottom: 28rpx; } |
|
|
|
.status-pill { margin-left: auto; font-size: 22rpx; font-weight: 500; padding: 4rpx 14rpx; border-radius: 6rpx; &.effective { color: #52c41a; background: #f6ffed; border: 1rpx solid #b7eb8f; } &.returned { color: #0e63e3; background: #f0f5ff; border: 1rpx solid #adc6ff; } } |
|
|
|
.status-pill { margin-left: auto; font-size: 22rpx; font-weight: 500; padding: 4rpx 14rpx; border-radius: 6rpx; &.effective { color: #52c41a; background: #f6ffed; border: 1rpx solid #b7eb8f; } &.returned { color: #0e63e3; background: #f0f5ff; border: 1rpx solid #adc6ff; } &.applying { color: #d46b08; background: #fff7e6; border: 1rpx solid #ffd591; } } |
|
|
|
.info-compact { padding-bottom: 8rpx; } |
|
|
|
.info-compact-row { display: flex; gap: 32rpx; margin-bottom: 12rpx; &:last-child { margin-bottom: 0; } } |
|
|
|
.info-compact-item { font-size: 26rpx; color: #666; } |
|
|
|
@@ -521,6 +614,9 @@ const handleSubmit = async () => { |
|
|
|
.return-text { display: block; font-size: 28rpx; color: #0e63e3; font-weight: 600; line-height: 1.5; } |
|
|
|
.return-time { display: block; font-size: 24rpx; color: #909399; margin-top: 8rpx; } |
|
|
|
.copy-return-no { display: block; text-align: right; font-size: 26rpx; color: #0e63e3; margin-top: 12rpx; } |
|
|
|
.reject-info { background: #fff2f0; border-left: 6rpx solid #ff4d4f; border-radius: 8rpx; padding: 24rpx; margin-bottom: 20rpx; } |
|
|
|
.reject-title { display: block; font-size: 28rpx; font-weight: 600; color: #a8071a; margin-bottom: 10rpx; } |
|
|
|
.reject-text { display: block; font-size: 26rpx; color: #606266; line-height: 1.6; } |
|
|
|
.receiver-info { padding-bottom: 8rpx; } |
|
|
|
.receiver-row { display: flex; gap: 20rpx; margin-bottom: 14rpx; &:last-child { margin-bottom: 0; } } |
|
|
|
.receiver-label { width: 120rpx; flex-shrink: 0; font-size: 26rpx; color: #909399; } |
|
|
|
@@ -543,4 +639,9 @@ const handleSubmit = async () => { |
|
|
|
.agree-row { display: flex; align-items: center; margin-bottom: 16rpx; padding-left: 4rpx; } |
|
|
|
.agree-text { font-size: 24rpx; color: #666; margin-left: 8rpx; } |
|
|
|
.agree-link { font-size: 24rpx; color: #0e63e3; } |
|
|
|
.apply-popup { width: 620rpx; background: #fff; border-radius: 16rpx; padding: 32rpx; } |
|
|
|
.apply-title { font-size: 32rpx; font-weight: 600; color: #303133; margin-bottom: 12rpx; } |
|
|
|
.apply-desc { font-size: 26rpx; color: #606266; line-height: 1.6; margin-bottom: 20rpx; } |
|
|
|
.apply-textarea { width: 100%; height: 180rpx; box-sizing: border-box; border: 1rpx solid #dcdfe6; border-radius: 8rpx; padding: 20rpx; font-size: 28rpx; color: #303133; background: #fff; } |
|
|
|
.apply-actions { display: flex; gap: 20rpx; margin-top: 24rpx; } |
|
|
|
</style> |