Преглед изворни кода

feat : 新增字段

master
leiyun пре 3 недеља
родитељ
комит
88015d59ed
1 измењених фајлова са 312 додато и 18 уклоњено
  1. +312
    -18
      pages/myinfo/myinfo.vue

+ 312
- 18
pages/myinfo/myinfo.vue Прегледај датотеку

@@ -12,23 +12,17 @@
<u-icon name="account-fill" size="18" color="#0e63e3" />
<text>基本信息</text>
</view>
<view class="form-group">
<text class="form-label">姓名</text>
<view class="readonly-input">{{ info.name }}</view>
</view>
<view class="form-group">
<text class="form-label">身份证号</text>
<view class="readonly-input">{{ maskedIdCard }}</view>
</view>
<view class="form-group">
<text class="form-label">手机号</text>
<view class="readonly-input">{{ maskedPhone }}</view>
</view>
<view class="form-group" v-if="info.gender">
<text class="form-label">性别</text>
<view class="readonly-input">{{ info.gender }}</view>
<view class="info-compact">
<view class="info-compact-row">
<text class="info-compact-item">姓名:{{ info.name }}</text>
<text class="info-compact-item" v-if="info.gender">性别:{{ info.gender }}</text>
</view>
<view class="info-compact-row">
<text class="info-compact-item">身份证:{{ maskedIdCard }}</text>
<text class="info-compact-item">手机号:{{ maskedPhone }}</text>
</view>
</view>
<view class="form-group" v-else>
<view class="form-group" v-if="!info.gender">
<text class="form-label">性别</text>
<view class="gender-row">
<view class="gender-item" :class="{ active: form.gender === '男' }" @tap="form.gender = '男'">男</view>
@@ -45,7 +39,7 @@
:customStyle="{ marginTop: '16rpx' }" />
</view>
<view class="form-group">
<text class="form-label">紧急联系人(选填)</text>
<text class="form-label">紧急联系人</text>
<view class="contact-row">
<view class="contact-input">
<u-input v-model="form.emergency_contact" placeholder="联系人姓名" border="surround" />
@@ -57,6 +51,85 @@
</view>
</view>

<!-- 情况描述 -->
<view class="section">
<view class="section-title">
<u-icon name="file-text" size="18" color="#fa541c" />
<text>情况描述</text>
</view>
<view class="form-group">
<text class="form-label">医院名称</text>
<u-input v-model="form.hospital" placeholder="请输入就诊医院名称" border="surround" />
</view>
<view class="form-group">
<text class="form-label">癌种</text>
<u-radio-group v-model="form.tag" placement="row" :wrap="true">
<u-radio v-for="t in tagOptions" :key="t" :label="t" :name="t"
activeColor="#0E63E3" :customStyle="{ marginRight: '24rpx', marginBottom: '16rpx' }" />
</u-radio-group>
</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">
<u-checkbox v-for="st in sampleTypeList" :key="st.id" :label="st.name" :name="st.name"
activeColor="#0E63E3" :customStyle="{ marginRight: '24rpx', marginBottom: '16rpx' }" />
</u-checkbox-group>
</view>
<view class="form-group" v-if="showWaxReturn">
<text class="form-label">{{ needReturnNames }}是否需寄回</text>
<u-radio-group v-model="form.wax_return" placement="row">
<u-radio label="是" :name="1" activeColor="#0E63E3" :customStyle="{ marginRight: '40rpx' }" />
<u-radio label="否" :name="0" activeColor="#0E63E3" />
</u-radio-group>
</view>
<!-- 寄回地址 -->
<template v-if="form.wax_return === 1 && showWaxReturn">
<view class="form-group">
<view style="display:flex;align-items:center;justify-content:space-between;">
<text class="form-label" style="margin-bottom:0;">收件人姓名</text>
<text class="fill-self-btn" @tap="fillSelfReturn">本人接收</text>
</view>
<u-input v-model="form.return_name" placeholder="请输入收件人姓名" border="surround" :customStyle="{ marginTop: '16rpx' }" />
</view>
<view class="form-group">
<text class="form-label">收件人电话</text>
<u-input v-model="form.return_phone" type="number" placeholder="请输入收件人电话" border="surround" maxlength="11" />
</view>
<view class="form-group">
<text class="form-label">收件地址</text>
<view class="region-row" @tap="showReturnRegionPicker = true">
<text :class="['region-text', returnRegionText ? '' : 'placeholder']">{{ returnRegionText || '请选择省/市/区' }}</text>
<text class="arrow">›</text>
</view>
<u-input v-model="form.return_address" placeholder="详细门牌号" border="surround"
:customStyle="{ marginTop: '16rpx' }" />
</view>
</template>
<template v-if="(form.sample_types && form.sample_types.length) || sampleRequired">
<view class="form-group">
<text class="form-label">报告接收邮箱</text>
<u-input v-model="form.report_email" placeholder="请输入邮箱地址" border="surround" />
</view>
<view class="form-group">
<text class="form-label">送检样本物流单号</text>
<u-input v-model="form.sample_tracking_no" placeholder="请输入物流单号" border="surround" />
</view>
<view class="form-group">
<text class="form-label">送检单照片(可上传多张)</text>
<view class="upload-row">
<view class="upload-item" v-for="(photo, idx) in form.sample_photos" :key="'sp'+idx">
<image class="upload-img" :src="photo" mode="aspectFill" @tap="previewSamplePhoto(idx)" />
<view class="upload-del" @tap="form.sample_photos.splice(idx, 1)">×</view>
</view>
<view class="upload-box" @tap="chooseSamplePhoto">
<text class="upload-icon">+</text>
<text class="upload-text">上传图片</text>
</view>
</view>
</view>
</template>
</view>

<!-- 资料上传 -->
<view class="section">
<view class="section-title">
@@ -144,6 +217,10 @@
<u-picker v-if="regionColumns[0].length" :show="showRegionPicker" :columns="regionColumns" @confirm="onRegionConfirm"
@cancel="showRegionPicker = false" @change="onRegionChange" :defaultIndex="regionDefaultIndex" />

<!-- 寄回地址地区选择器 -->
<u-picker v-if="regionColumns[0].length" :show="showReturnRegionPicker" :columns="regionColumns" @confirm="onReturnRegionConfirm"
@cancel="showReturnRegionPicker = false" @change="onRegionChange" :defaultIndex="returnRegionDefaultIndex" />

<!-- 已通过重新提交确认弹窗 -->
<u-popup :show="showConfirmPopup" mode="center" round="12" :safeAreaInsetBottom="false" @close="showConfirmPopup = false">
<view class="confirm-popup">
@@ -170,9 +247,22 @@ const form = reactive({
city_code: '',
district_code: '',
address: '',
hospital: '',
emergency_contact: '',
emergency_phone: '',
tag: '',
documents: [],
sample_types: [],
wax_return: 0,
return_name: '',
return_phone: '',
return_province_code: '',
return_city_code: '',
return_district_code: '',
return_address: '',
report_email: '',
sample_tracking_no: '',
sample_photos: [],
sign_income: '',
sign_privacy: '',
sign_privacy_jhr: '',
@@ -185,6 +275,75 @@ const showConfirmPopup = ref(false)
const subscribeTmplId = ref('')
const agreed = ref(false)

// 瘤种选项和送检样本类型
const tagOptions = ref([])
const sampleTypeList = ref([])
const sampleRequired = ref(false)
const showReturnRegionPicker = ref(false)
const returnRegionDefaultIndex = ref([0, 0, 0])

// 是否显示"是否需寄回"
const showWaxReturn = computed(() => {
if (!form.sample_types || !form.sample_types.length) return false
return form.sample_types.some(name => {
const st = sampleTypeList.value.find(s => s.name === name)
return st && st.need_return
})
})

// 需要寄回的样本类型名称(用"、"分隔)
const needReturnNames = computed(() => {
if (!form.sample_types || !form.sample_types.length) return ''
const names = form.sample_types.filter(name => {
const st = sampleTypeList.value.find(s => s.name === name)
return st && st.need_return
})
return names.join('、')
})

// 寄回地址文本
const returnRegionText = computed(() => {
const parts = []
if (form.return_province_code) {
const p = allRegions.value.find(r => r.code === form.return_province_code)
if (p) parts.push(p.name)
}
if (form.return_city_code) {
const prov = allRegions.value.find(r => r.code === form.return_province_code)
if (prov && prov.children) {
const c = prov.children.find(r => r.code === form.return_city_code)
if (c) parts.push(c.name)
}
}
if (form.return_district_code) {
const prov = allRegions.value.find(r => r.code === form.return_province_code)
if (prov && prov.children) {
const city = prov.children.find(r => r.code === form.return_city_code)
if (city && city.children) {
const d = city.children.find(r => r.code === form.return_district_code)
if (d) parts.push(d.name)
}
}
}
return parts.join(' ')
})

const onSampleTypesChange = () => {
// 如果取消了所有 need_return 的样本类型,重置寄回选项
if (!showWaxReturn.value) {
form.wax_return = 0
}
}

const fillSelfReturn = () => {
form.return_name = info.value.name || ''
form.return_phone = info.value.phone || ''
form.return_province_code = form.province_code
form.return_city_code = form.city_code
form.return_district_code = form.district_code
form.return_address = form.address
}

// 签署时的额外信息(用于重签回显)
const signExtra = reactive({
income_amount: '',
@@ -227,7 +386,7 @@ const regionDefaultIndex = ref([0, 0, 0])

const maskedIdCard = computed(() => {
const v = info.value.id_card || ''
if (v.length === 18) return v.slice(0, 3) + '***********' + v.slice(-4)
if (v.length === 18) return v.slice(0, 3) + '****' + v.slice(-4)
return v
})

@@ -308,6 +467,8 @@ onLoad(async () => {
await loadRegions()
await loadInfo()
loadSubscribeConfig()
loadTagOptions()
loadSampleTypes()
})

onBeforeUnmount(() => {
@@ -395,9 +556,22 @@ const loadInfo = async () => {
form.city_code = res.data.city_code || ''
form.district_code = res.data.district_code || ''
form.address = res.data.address || ''
form.hospital = res.data.hospital || ''
form.emergency_contact = res.data.emergency_contact || ''
form.emergency_phone = res.data.emergency_phone || ''
form.tag = res.data.tag || ''
form.documents = res.data.documents || []
form.sample_types = res.data.sample_types || []
form.wax_return = res.data.wax_return || 0
form.return_name = res.data.return_name || ''
form.return_phone = res.data.return_phone || ''
form.return_province_code = res.data.return_province_code || ''
form.return_city_code = res.data.return_city_code || ''
form.return_district_code = res.data.return_district_code || ''
form.return_address = res.data.return_address || ''
form.report_email = res.data.report_email || ''
form.sample_tracking_no = res.data.sample_tracking_no || ''
form.sample_photos = res.data.sample_photos || []
form.sign_income = res.data.sign_income || ''
form.sign_privacy = res.data.sign_privacy || ''
form.sign_privacy_jhr = res.data.sign_privacy_jhr || ''
@@ -423,6 +597,55 @@ const loadInfo = async () => {
} catch (e) {}
}

const loadTagOptions = async () => {
try {
const res = await get('/common/tagOptions')
tagOptions.value = res.data || []
} catch (e) {}
}

const loadSampleTypes = async () => {
try {
const res = await get('/common/sampleTypes')
sampleTypeList.value = (res.data && res.data.list) || []
sampleRequired.value = (res.data && res.data.required) || false
} catch (e) {}
}

const chooseSamplePhoto = () => {
uni.chooseImage({
count: 9 - form.sample_photos.length,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: async (res) => {
for (const filePath of res.tempFilePaths) {
try {
const uploadRes = await upload('/api/mp/upload', { filePath, name: 'file' })
if (uploadRes.data && uploadRes.data.url) {
form.sample_photos.push(uploadRes.data.url)
}
} catch (e) {}
}
}
})
}

const previewSamplePhoto = (idx) => {
uni.previewImage({ urls: form.sample_photos, current: idx })
}

const onReturnRegionConfirm = (e) => {
const idxs = e.indexs || e.index || [0, 0, 0]
const provinces = allRegions.value
const prov = provinces[idxs[0]]
const city = prov && prov.children ? prov.children[idxs[1]] : null
const dist = city && city.children ? city.children[idxs[2]] : null
form.return_province_code = prov ? prov.code : ''
form.return_city_code = city ? city.code : ''
form.return_district_code = dist ? dist.code : ''
showReturnRegionPicker.value = false
}

const chooseDocument = () => {
uni.chooseImage({
count: 9 - form.documents.length,
@@ -462,6 +685,35 @@ const handleSubmit = async () => {
if (!form.address.trim()) {
return uni.showToast({ title: '请填写详细地址', icon: 'none' })
}
if (!form.emergency_contact || !form.emergency_phone) {
return uni.showToast({ title: '请填写紧急联系人信息', icon: 'none' })
}
if (form.emergency_phone === info.value.phone) {
return uni.showToast({ title: '紧急联系人电话不能与本人手机号一致', icon: 'none' })
}
if (!form.hospital || !form.hospital.trim()) {
return uni.showToast({ title: '请填写医院名称', icon: 'none' })
}
if (!form.tag) {
return uni.showToast({ title: '请选择癌种', icon: 'none' })
}
// 送检样本校验
if (sampleRequired.value && (!form.sample_types || form.sample_types.length === 0)) {
return uni.showToast({ title: '请选择送检样本类型', icon: 'none' })
}
// 寄回信息校验
if (form.wax_return === 1 && showWaxReturn.value) {
if (!form.return_name) return uni.showToast({ title: '请输入收件人姓名', icon: 'none' })
if (!form.return_phone) return uni.showToast({ title: '请输入收件人电话', icon: 'none' })
if (!form.return_province_code) return uni.showToast({ title: '请选择收件地址', icon: 'none' })
if (!form.return_address) return uni.showToast({ title: '请输入收件详细地址', icon: 'none' })
}
// 选了送检样本后,邮箱/物流单号/送检照片必填
if (form.sample_types && form.sample_types.length > 0) {
if (!form.report_email) return uni.showToast({ title: '请输入报告接收邮箱', icon: 'none' })
if (!form.sample_tracking_no) return uni.showToast({ title: '请输入送检样本物流单号', icon: 'none' })
if (!form.sample_photos || form.sample_photos.length === 0) return uni.showToast({ title: '请上传送检单照片', icon: 'none' })
}
// 资料上传校验:至少上传一个
if (!form.documents || form.documents.length === 0) {
return uni.showToast({ title: '请至少上传一份检查报告或诊断证明', icon: 'none' })
@@ -499,9 +751,22 @@ const doSubmit = async () => {
city_code: form.city_code,
district_code: form.district_code,
address: form.address.trim(),
hospital: form.hospital,
emergency_contact: form.emergency_contact,
emergency_phone: form.emergency_phone,
tag: form.tag,
documents: form.documents,
sample_types: form.sample_types,
wax_return: form.wax_return,
return_name: form.return_name,
return_phone: form.return_phone,
return_province_code: form.return_province_code,
return_city_code: form.return_city_code,
return_district_code: form.return_district_code,
return_address: form.return_address,
report_email: form.report_email,
sample_tracking_no: form.sample_tracking_no,
sample_photos: form.sample_photos,
sign_income: form.sign_income,
sign_privacy: form.sign_privacy,
sign_privacy_jhr: form.sign_privacy_jhr,
@@ -578,6 +843,35 @@ const doSubmit = async () => {
}
}

.info-compact {
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
}

.info-compact-row {
display: flex;
gap: 32rpx;
margin-bottom: 12rpx;

&:last-child {
margin-bottom: 0;
}
}

.info-compact-item {
font-size: 26rpx;
color: #666;
}

.fill-self-btn {
font-size: 24rpx;
color: #0e63e3;
padding: 6rpx 16rpx;
border: 1rpx solid #d0e0ff;
border-radius: 20rpx;
background: #f0f5ff;
}

.form-label {
font-size: 28rpx;
color: #555;


Loading…
Откажи
Сачувај