317 lines
8.4 KiB
Vue
Raw Permalink Normal View History

2026-07-27 11:26:39 +08:00
<template>
<view class="container" :class="{ 'container--elder': elderMode }">
<template v-if="logined">
<view class="main">
<scroll-view scroll-y="true" class="main-scroll">
<view class="card">
<uni-list>
<uni-list-item direction="column">
<template v-slot:body>
<view class="info-item">
<text class="item-label">姓名</text>
<input v-model="form.name" :maxlength="20" class="item-value" type="text"
placeholder="请输入姓名" />
</view>
<view class="info-item">
<text class="item-label">证件类型</text>
<text class="item-value">身份证</text>
</view>
<view class="info-item">
<text class="item-label">证件号</text>
<input v-model="form.certNo" :maxlength="18" class="item-value" type="idcard"
placeholder="请输入证件号" />
</view>
<view class="info-item">
<text class="item-label">手机号</text>
<input v-model="form.mobile" :maxlength="11" class="item-value" type="number"
placeholder="请输入手机号" />
</view>
<view class="info-item address-item">
<view class="address-header">
<text class="item-label">地址</text>
<text class="choose-address" @click="chooseAddress">选择地址</text>
</view>
<textarea v-model="form.address" :maxlength="200" class="address-textarea"
placeholder="请输入详细地址"></textarea>
</view>
</template>
</uni-list-item>
</uni-list>
</view>
</scroll-view>
</view>
<view class="save-footer">
<view class="save-btn" :class="{ 'save-btn--disabled': loading }" @click="confirm">
{{ loading ? '保存中...' : '保存' }}
</view>
</view>
<view class="safearea-bottom"></view>
</template>
<re-login v-else height="80vh" />
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import useUser from '@/hooks/useUser';
import { addHlwPatient, getHlwPatient, updateHlwPatient } from '@/utils/api';
import { isChinaId } from '@/utils/validator';
import { toast } from '@/utils/widget';
import reLogin from '@/components/re-login.vue';
const id = ref('');
const loading = ref(false);
const elderMode = ref(false);
const loadedPatientKey = ref('');
const form = ref({
name: '',
certNo: '',
mobile: '',
address: '',
});
const { userInfo, logined } = useUser();
const accountId = computed(() => userInfo.value && userInfo.value.userId ? userInfo.value.userId : '');
function validateForm() {
if (!form.value.name.trim()) {
toast('姓名不能为空');
return false;
}
if (!form.value.certNo.trim()) {
toast('证件号不能为空');
return false;
}
if (!isChinaId(form.value.certNo.trim())[0]) {
toast('请输入有效的身份证号');
return false;
}
if (!/^1[3-9]\d{9}$/.test(form.value.mobile.trim())) {
toast('请输入有效的手机号');
return false;
}
return true;
}
function chooseAddress() {
uni.chooseLocation({
success: location => {
const address = typeof location.address === 'string' ? location.address.trim() : '';
const name = typeof location.name === 'string' ? location.name.trim() : '';
form.value.address = address && name && !address.endsWith(name)
? `${address}${name}`
: address || name;
},
fail: error => {
if (!error || !/cancel/i.test(error.errMsg || '')) {
toast('选择地址失败');
}
},
});
}
async function confirm() {
if (loading.value || !validateForm()) return;
if (!accountId.value) {
toast('请先登录');
return;
}
loading.value = true;
try {
const payload = {
accountId: accountId.value,
name: form.value.name.trim(),
certNo: form.value.certNo.trim(),
mobile: form.value.mobile.trim(),
address: form.value.address.trim(),
};
const api = id.value ? updateHlwPatient : addHlwPatient;
const res = await api(id.value ? { ...payload, id: id.value } : payload);
if (!res || !res.success) {
toast((res && res.message) || '保存失败');
return;
}
toast('保存成功');
const pages = getCurrentPages();
if (pages.length > 1) {
uni.navigateBack();
} else {
uni.redirectTo({ url: '/pages/member/list' });
}
} catch (error) {
toast(error.message || error || '保存失败');
} finally {
loading.value = false;
}
}
async function loadPatient() {
if (!id.value || !accountId.value) return;
const patientKey = `${accountId.value}:${id.value}`;
if (loadedPatientKey.value === patientKey) return;
loading.value = true;
try {
const res = await getHlwPatient(accountId.value, id.value);
if (!res || !res.success || !res.data) {
toast((res && res.message) || '查询就诊人失败');
return;
}
form.value = {
name: res.data.name || '',
certNo: res.data.certNo || '',
mobile: res.data.mobile || '',
address: res.data.address || '',
};
loadedPatientKey.value = patientKey;
} catch (error) {
toast(error.message || error || '查询就诊人失败');
} finally {
loading.value = false;
}
}
onLoad(options => {
id.value = options.id || '';
uni.setNavigationBarTitle({ title: id.value ? '编辑就诊人' : '新增就诊人' });
const savedElderMode = uni.getStorageSync('elderMode');
if (savedElderMode !== null && savedElderMode !== undefined) {
elderMode.value = savedElderMode;
}
});
watch([id, accountId], loadPatient, { immediate: true });
</script>
<style lang="scss">
.container {
display: flex;
flex-direction: column;
background-color: #f5f5f5;
height: 100vh;
--font-scale: 1;
--spacing-scale: 1;
--border-radius-scale: 1;
@at-root &--elder {
--font-scale: 1.4;
--spacing-scale: 1.2;
--border-radius-scale: 1.25;
}
}
.main {
position: relative;
flex-grow: 1;
}
.main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.card {
margin: calc(30rpx * var(--spacing-scale));
border-radius: calc(16rpx * var(--border-radius-scale));
overflow: hidden;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
}
.info-item {
background: #fff;
display: flex;
justify-content: space-between;
align-items: center;
padding: calc(24rpx * var(--spacing-scale)) calc(30rpx * var(--spacing-scale));
border-bottom: 1rpx solid #eee;
min-height: calc(80rpx * var(--spacing-scale));
&:last-child {
border-bottom: none;
}
}
.address-item {
display: block;
}
.address-header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-bottom: calc(20rpx * var(--spacing-scale));
}
.choose-address {
color: $theme-brown-primary;
font-size: calc(30rpx * var(--font-scale));
font-weight: 500;
}
.address-textarea {
box-sizing: border-box;
width: 100%;
height: calc(160rpx * var(--spacing-scale));
padding: calc(20rpx * var(--spacing-scale));
border-radius: calc(8rpx * var(--border-radius-scale));
background: #f7f7f7;
color: #333;
font-size: calc(30rpx * var(--font-scale));
line-height: 1.5;
}
.item-label {
color: #666;
font-size: calc(30rpx * var(--font-scale));
width: calc(200rpx * var(--spacing-scale));
font-weight: 500;
}
.item-value {
color: #333;
font-size: calc(30rpx * var(--font-scale));
font-weight: 500;
flex: 1;
text-align: right;
.container--elder & {
font-weight: 600;
}
}
.save-footer {
padding: calc(24rpx * var(--spacing-scale)) calc(30rpx * var(--spacing-scale));
background: white;
}
.save-btn {
height: calc(80rpx * var(--spacing-scale));
background: $theme-brown-primary;
color: white;
font-size: calc(28rpx * var(--font-scale));
border-radius: calc(16rpx * var(--border-radius-scale));
text-align: center;
line-height: calc(80rpx * var(--spacing-scale));
font-weight: 500;
&--disabled {
opacity: 0.6;
}
}
.safearea-bottom {
height: env(safe-area-inset-bottom);
flex-shrink: 0;
}
</style>