| @@ -67,7 +67,7 @@ const countdownText = computed(() => { | |||
| onShow(() => { | |||
| const info = getUserInfo() | |||
| currentPhone.value = info?.patient?.phone || '' | |||
| currentPhone.value = (info && info.patient && info.patient.phone) || '' | |||
| }) | |||
| const handleSendCode = async () => { | |||
| @@ -19,7 +19,7 @@ const content = ref('') | |||
| const loaded = ref(false) | |||
| onLoad((options) => { | |||
| const key = options?.key || '' | |||
| const key = (options && options.key) || '' | |||
| if (key) { | |||
| loadContent(key) | |||
| } | |||
| @@ -32,9 +32,12 @@ const userInfo = ref(null) | |||
| const isLoggedIn = ref(false) | |||
| // 患者状态 | |||
| const patient = computed(() => userInfo.value?.patient || null) | |||
| const isAuthed = computed(() => patient.value?.auth_status === 1) | |||
| const patientStatus = computed(() => patient.value?.status ?? null) | |||
| const patient = computed(() => (userInfo.value && userInfo.value.patient) || null) | |||
| const isAuthed = computed(() => patient.value && patient.value.auth_status === 1) | |||
| const patientStatus = computed(() => { | |||
| if (!patient.value || patient.value.status === undefined || patient.value.status === null) return null | |||
| return patient.value.status | |||
| }) | |||
| // 按钮文案和样式 | |||
| const btnText = computed(() => { | |||
| @@ -130,6 +130,13 @@ | |||
| <!-- 提交按钮 --> | |||
| <view class="btn-wrap"> | |||
| <view class="agree-row" @tap="agreed = !agreed"> | |||
| <u-checkbox-group> | |||
| <u-checkbox :checked="agreed" shape="circle" activeColor="#0E63E3" size="18" @change="agreed = !agreed" /> | |||
| </u-checkbox-group> | |||
| <text class="agree-text">请阅读并同意</text> | |||
| <text class="agree-link" @tap.stop="openNotice">《患者告知书》</text> | |||
| </view> | |||
| <u-button text="提交审核" :loading="submitting" @click="handleSubmit" color="#0E63E3" size="large" /> | |||
| </view> | |||
| @@ -176,6 +183,7 @@ const submitting = ref(false) | |||
| const showRegionPicker = ref(false) | |||
| const showConfirmPopup = ref(false) | |||
| const subscribeTmplId = ref('') | |||
| const agreed = ref(false) | |||
| // 签署时的额外信息(用于重签回显) | |||
| const signExtra = reactive({ | |||
| @@ -437,7 +445,14 @@ const previewImage = (idx) => { | |||
| uni.previewImage({ urls: form.documents, current: idx }) | |||
| } | |||
| const openNotice = () => { | |||
| uni.navigateTo({ url: '/pages/content/content?key=patient_information_sheet' }) | |||
| } | |||
| const handleSubmit = async () => { | |||
| if (!agreed.value) { | |||
| return uni.showToast({ title: '请阅读并同意《患者告知书》', icon: 'none' }) | |||
| } | |||
| if (!info.value.gender && !form.gender) { | |||
| return uni.showToast({ title: '请选择性别', icon: 'none' }) | |||
| } | |||
| @@ -775,6 +790,24 @@ const doSubmit = async () => { | |||
| z-index: 100; | |||
| } | |||
| .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; | |||
| } | |||
| .confirm-popup { | |||
| padding: 48rpx 40rpx 40rpx; | |||
| width: 560rpx; | |||
| @@ -5,7 +5,7 @@ | |||
| <image class="header-bg" src="https://cdn.csybhelp.com/images/cytx/profile-bg.jpg" mode="aspectFill" /> | |||
| <view class="user-row"> | |||
| <view class="avatar-wrap" @tap="isLoggedIn && changeAvatar()"> | |||
| <image class="avatar" :src="userInfo?.avatar || 'https://cdn.csybhelp.com/images/cytx/default-avatar.jpg'" | |||
| <image class="avatar" :src="(userInfo && userInfo.avatar) || 'https://cdn.csybhelp.com/images/cytx/default-avatar.jpg'" | |||
| mode="aspectFill" /> | |||
| <view v-if="isLoggedIn" class="camera-icon"> | |||
| <u-icon name="camera-fill" size="20" color="#666" /> | |||
| @@ -13,7 +13,7 @@ | |||
| </view> | |||
| <view class="info" @tap="!isLoggedIn && goLogin()"> | |||
| <view class="name">{{ displayName }}</view> | |||
| <view v-if="isLoggedIn && userInfo?.patient?.patient_no" class="patient-no">{{ userInfo.patient.patient_no }}</view> | |||
| <view v-if="isLoggedIn && userInfo && userInfo.patient && userInfo.patient.patient_no" class="patient-no">{{ userInfo.patient.patient_no }}</view> | |||
| </view> | |||
| </view> | |||
| </view> | |||
| @@ -96,9 +96,9 @@ const userInfo = ref(getUserInfo()) | |||
| const isLoggedIn = ref(!!getToken()) | |||
| const unreadCount = ref(0) | |||
| const isAuthed = computed(() => userInfo.value?.patient?.auth_status === 1) | |||
| const isAuthed = computed(() => userInfo.value && userInfo.value.patient && userInfo.value.patient.auth_status === 1) | |||
| const patientStatus = computed(() => { | |||
| const p = userInfo.value?.patient | |||
| const p = userInfo.value && userInfo.value.patient | |||
| if (!p) return null | |||
| return p.status | |||
| }) | |||
| @@ -106,8 +106,8 @@ const isRejected = computed(() => patientStatus.value === 2) | |||
| const displayName = computed(() => { | |||
| if (!isLoggedIn.value) return '点击登录' | |||
| if (isAuthed.value && userInfo.value?.patient?.name) return userInfo.value.patient.name | |||
| return userInfo.value?.nickname || '微信用户' | |||
| if (isAuthed.value && userInfo.value && userInfo.value.patient && userInfo.value.patient.name) return userInfo.value.patient.name | |||
| return (userInfo.value && userInfo.value.nickname) || '微信用户' | |||
| }) | |||
| onShow(() => { | |||
| @@ -127,7 +127,7 @@ const fetchUserInfo = async () => { | |||
| userInfo.value = res.data | |||
| setUserInfo(res.data) | |||
| } catch (e) { | |||
| if (e?.code === 1009) { | |||
| if (e && e.code === 1009) { | |||
| clearAll() | |||
| userInfo.value = null | |||
| } | |||
| @@ -137,7 +137,7 @@ const fetchUserInfo = async () => { | |||
| const fetchUnreadCount = async () => { | |||
| try { | |||
| const res = await get('/api/mp/unreadCount') | |||
| unreadCount.value = res.data?.count || 0 | |||
| unreadCount.value = (res.data && res.data.count) || 0 | |||
| } catch (e) {} | |||
| } | |||
| @@ -222,7 +222,7 @@ const changeAvatar = () => { | |||
| try { | |||
| uni.showLoading({ title: '上传中...' }) | |||
| const uploadRes = await upload('/api/mp/upload', { filePath, name: 'file' }) | |||
| if (!uploadRes.data?.url) throw { msg: '上传失败' } | |||
| if (!(uploadRes.data && uploadRes.data.url)) throw { msg: '上传失败' } | |||
| const avatarUrl = uploadRes.data.url | |||
| await post('/api/mp/updateAvatar', { avatar: avatarUrl }) | |||
| if (userInfo.value) { | |||
| @@ -231,7 +231,7 @@ const changeAvatar = () => { | |||
| } | |||
| uni.showToast({ title: '头像已更新', icon: 'success' }) | |||
| } catch (e) { | |||
| if (e?.msg) uni.showToast({ title: e.msg, icon: 'none' }) | |||
| if (e && e.msg) uni.showToast({ title: e.msg, icon: 'none' }) | |||
| } finally { | |||
| uni.hideLoading() | |||
| } | |||
| @@ -278,7 +278,7 @@ const sendSms = async () => { | |||
| try { | |||
| const res = await post('/api/mp/sendSmsCode', { mobile: form.phone, bizType: 'real_name_auth' }) | |||
| // 开发环境可能返回验证码 | |||
| if (res.data?.code) { | |||
| if (res.data && res.data.code) { | |||
| uni.showToast({ title: `验证码: ${res.data.code}`, icon: 'none', duration: 3000 }) | |||
| } else { | |||
| uni.showToast({ title: '验证码已发送', icon: 'none' }) | |||
| @@ -354,8 +354,8 @@ const doSubmit = async (confirmBind) => { | |||
| if (e && e.code === 1010) { | |||
| // 患者已存在,弹出确认绑定弹窗 | |||
| bindPatientInfo.value = { | |||
| name: e.data?.patientName || '', | |||
| phone: e.data?.patientPhone || '' | |||
| name: (e.data && e.data.patientName) || '', | |||
| phone: (e.data && e.data.patientPhone) || '' | |||
| } | |||
| showBindPopup.value = true | |||
| } else if (e && e.msg) { | |||
| @@ -0,0 +1,27 @@ | |||
| -----BEGIN RSA PRIVATE KEY----- | |||
| MIIEowIBAAKCAQEAwtVO/Qlh6bgOVAdSUFk4fgqucdl8xog1lALeRrcDBrFk5Mh6 | |||
| 5TqB7Y1ws+Nl4n3X59Om2hM0J/0C7pOuG/oLNiR+FFxySESwxIs7okvWa7LpPxTt | |||
| Elocy0zELu9lifZGYxCfCXRalCCoq6SiPdQJXZ145cRvdWbonxdd3bYhGW66lCn4 | |||
| VS5tLOtBhr3FEqMMUY2wTppU1P1C8SZ7zh4IU2YSVC2TdAwV+1d2OBBJ/u51+LFB | |||
| 1losqPEp4yaBm5Kmhar16yL9xxVLMSy83H2MoxU162Mz1fHR5jaQIRRxqhdjdiAB | |||
| gpJpZToCWkvE5GQqGA4MnEy6F2nBlYSZep9wfwIDAQABAoIBAH0avyeXuLl8qCao | |||
| tOBHChFVBoKwZoCMweqSlOvPZDAOBH0rhk5e7UL+SVoZMDjpGZQQwdjR7/GlcxaC | |||
| 2Y+5VS2k7Rhh7Dgfc2ohBV/HVp29Oix5YWkhV8/rMSX6LrcR3kyKRbSqc+cduXDN | |||
| vCf7WTA1h4XyRqeaNtDBDlLpOgO7hvtxfhi3dwXxJVcjePb4LMWzZdTQul8RvJj+ | |||
| RuShXm9I25tw1DEL0QUYVasaYT+/bdUm/IKahO7qB40HaV7/OFwE449Np1FIBFUX | |||
| Crztg4X9Gl0xfSld463TNKPegH9wX2DVvAk4fQev6vv22ldJ7Bw/u8tmSuldKnT2 | |||
| n6pshQECgYEA/hKknNbuCO3/q1ykjoEiVbsilraMcxMd3wO8az8j71glaWEsNlJ5 | |||
| T6OAvKFQwTUO5OGWS1mrrfFyvEJ+J0IaJh9Sig0xRlWJ2XsQaiI6Wff9oCSUhzUD | |||
| 3EUn0vovoPqiFAdpUUL1IiPhxXd83DgMOerMaHB1wGRqUjO++W4SksECgYEAxE+i | |||
| bS6r8m4BI2HBnLSPct5MXqOJRQCj3FALa6IQn7Y18qQpjX6f12hRAg6pwPYn8vrs | |||
| FiW4RIbbjKuswT2ww6+3HhV9dbN30lUuopcTJhdJd2s3lfgPqsf8Vwe0HAviL3BW | |||
| Up6oWTl0cskHJ14SyUQ9hDoJrBb7wwcAbFJpEz8CgYEA/Ucwenl4ScaYPQfZs4Xf | |||
| 6H7o+D16vays9okO6ArFk+/XO7n3DSAidtWTnHdjvXdbJagM34jAsGIl8q6GfDRV | |||
| RPOsoJqOKINVLEyWDHeam92wJFjTCAY9lvQJwzRNDrlLoZPR1YReQm5qvyNigVYO | |||
| Oh5rLyINAIIZy2ByXMzyDwECgYBMRDfxPQGWVMBic5cZf1h/ovd+iQBKa349mGdn | |||
| cHYO5mY9FyQBkaEduaxHJVUz3y4UCwHvdMYK8W2YUBX0mTf0Pm7g5C5yrL+vWmKc | |||
| zh6lXMSw/VmCDPZhPgK9+QMzJjbAgV84B+WVjGm+MnVyCO05fiZ8GWQqlF9JHI5A | |||
| hx/FVwKBgDR5Hyxng8qyAMD6cG3u7Fs+coIdjGWZr6k1+FxlPWF/E9R4KDoa3ylL | |||
| OMTXiyFxbtroNCB5cHsdQLPOJbEg2aU8ldFm/KCOE0JB59Y9WgyZ7XTHKA6DwGw4 | |||
| 6yOxyWd4+3RtcCrEfJ8OFuUGrLRJHpI3IBhsZIlvTlkcV5RKtegB | |||
| -----END RSA PRIVATE KEY----- | |||