fix: 优化个人信息完善提示逻辑,更新搜索占位符和提示信息
This commit is contained in:
parent
f68c473191
commit
7d445f7b8b
@ -9,11 +9,15 @@ export default function useInfoCheck() {
|
|||||||
function withInfo(fn) {
|
function withInfo(fn) {
|
||||||
return async (...args) => {
|
return async (...args) => {
|
||||||
if (!doctorInfo.value || !doctorInfo.value.anotherName) {
|
if (!doctorInfo.value || !doctorInfo.value.anotherName) {
|
||||||
await confirm('请先完善您的个人信息,方可使用该功能!', { cancelText: '再等等', confirmText: '去完善' })
|
try {
|
||||||
|
await confirm('请先完善您的个人信息,方可使用该功能!', { cancelText: '再等等', confirmText: '去完善' })
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
return uni.navigateTo({ url: '/pages/work/profile' });
|
return uni.navigateTo({ url: '/pages/work/profile' });
|
||||||
}
|
}
|
||||||
return fn(...args);
|
return fn(...args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { withInfo }
|
return { withInfo }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
<uni-icons type="search" size="18" color="#999" class="search-icon"></uni-icons>
|
<uni-icons type="search" size="18" color="#999" class="search-icon"></uni-icons>
|
||||||
<input
|
<input
|
||||||
class="search-input"
|
class="search-input"
|
||||||
placeholder="搜索患者名称/手机号/院内ID号"
|
placeholder="搜索患者名称/手机号/病案号"
|
||||||
v-model="searchQuery"
|
v-model="searchQuery"
|
||||||
confirm-type="search"
|
confirm-type="search"
|
||||||
focus
|
focus
|
||||||
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
<!-- History or Suggestions (when no search) -->
|
<!-- History or Suggestions (when no search) -->
|
||||||
<view v-else class="search-tips">
|
<view v-else class="search-tips">
|
||||||
<text class="tips-text">输入患者名称、手机号或院内ID号进行搜索</text>
|
<text class="tips-text">输入患者名称、手机号或病案号进行搜索</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@ -73,6 +73,7 @@ import { toast } from '@/utils/widget';
|
|||||||
const searchQuery = ref('');
|
const searchQuery = ref('');
|
||||||
const searchResultsRaw = ref([]);
|
const searchResultsRaw = ref([]);
|
||||||
const searching = ref(false);
|
const searching = ref(false);
|
||||||
|
const searchSeq = ref(0);
|
||||||
|
|
||||||
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
const CURRENT_TEAM_STORAGE_KEY = 'ykt_case_current_team';
|
||||||
const DETAIL_STORAGE_KEY = 'ykt_case_archive_detail';
|
const DETAIL_STORAGE_KEY = 'ykt_case_archive_detail';
|
||||||
@ -111,11 +112,29 @@ function formatPatient(raw) {
|
|||||||
const mobiles = asArray(raw?.mobiles).map(String).filter(Boolean);
|
const mobiles = asArray(raw?.mobiles).map(String).filter(Boolean);
|
||||||
const mobile = raw?.mobile ? String(raw.mobile) : (mobiles[0] || '');
|
const mobile = raw?.mobile ? String(raw.mobile) : (mobiles[0] || '');
|
||||||
|
|
||||||
|
const customerNumber = raw?.customerNumber || raw?.hospitalId || '';
|
||||||
|
const customerProfileNo2 = raw?.customerProfileNo2 || '';
|
||||||
|
const customerProfileNo3 = raw?.customerProfileNo3 || '';
|
||||||
|
|
||||||
|
function normalizeRecordTypeLabel(value) {
|
||||||
|
const s = String(value || '').trim();
|
||||||
|
if (!s) return '';
|
||||||
|
const lower = s.toLowerCase();
|
||||||
|
const base = lower.endsWith('record') && s.length > 6 ? s.slice(0, -6) : s;
|
||||||
|
const baseLower = String(base).toLowerCase();
|
||||||
|
if (baseLower === 'outpatient' || baseLower === 'out_patient' || baseLower === 'out-patient') return '门诊记录';
|
||||||
|
if (baseLower === 'inhospital' || baseLower === 'in_hospital' || baseLower === 'in-hospital' || baseLower === 'inpatient') return '住院记录';
|
||||||
|
if (baseLower === 'preconsultation' || baseLower === 'pre_consultation' || baseLower === 'pre-consultation' || baseLower === 'preconsultationtemplate') return '预问诊记录';
|
||||||
|
if (baseLower === 'physicalexaminationtemplate' || baseLower === 'physicalexamination' || baseLower === 'physical_examination') return '体检记录';
|
||||||
|
// 如果已经是中文(或后端已给展示名),直接返回
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
// 解析病历信息
|
// 解析病历信息
|
||||||
let record = null;
|
let record = null;
|
||||||
if (raw?.latestRecord && typeof raw.latestRecord === 'object') {
|
if (raw?.latestRecord && typeof raw.latestRecord === 'object') {
|
||||||
const lr = raw.latestRecord;
|
const lr = raw.latestRecord;
|
||||||
const type = lr.type || '';
|
const type = normalizeRecordTypeLabel(lr.type || lr.medicalTypeName || lr.medicalType || '');
|
||||||
const date = lr.date || '';
|
const date = lr.date || '';
|
||||||
const diagnosis = lr.diagnosis || '';
|
const diagnosis = lr.diagnosis || '';
|
||||||
if (type || date || diagnosis) {
|
if (type || date || diagnosis) {
|
||||||
@ -139,10 +158,79 @@ function formatPatient(raw) {
|
|||||||
record,
|
record,
|
||||||
createTime: raw?.createTime || '',
|
createTime: raw?.createTime || '',
|
||||||
creator: raw?.creatorName || raw?.creator || '',
|
creator: raw?.creatorName || raw?.creator || '',
|
||||||
hospitalId: raw?.customerNumber || raw?.hospitalId || '',
|
hospitalId: customerNumber,
|
||||||
|
customerNumber,
|
||||||
|
customerProfileNo2,
|
||||||
|
customerProfileNo3,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeText(value) {
|
||||||
|
return String(value || '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeDigits(value) {
|
||||||
|
const s = normalizeText(value);
|
||||||
|
return s.replace(/\D/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isChinaMobile(value) {
|
||||||
|
const digits = normalizeDigits(value);
|
||||||
|
return /^1[3-9]\d{9}$/.test(digits);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLikelyArchiveNo(value) {
|
||||||
|
const s = normalizeText(value);
|
||||||
|
if (!s) return false;
|
||||||
|
if (/[\u4e00-\u9fa5]/.test(s)) return false; // 中文一般是姓名
|
||||||
|
if (isChinaMobile(s)) return false;
|
||||||
|
// 病案号一般为数字/字母组合(或纯数字)
|
||||||
|
return /^[0-9A-Za-z-]{3,}$/.test(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesAnyArchiveNo(patient, q) {
|
||||||
|
const needle = normalizeText(q).toLowerCase();
|
||||||
|
if (!needle) return false;
|
||||||
|
const values = [
|
||||||
|
patient?.customerNumber,
|
||||||
|
patient?.customerProfileNo2,
|
||||||
|
patient?.customerProfileNo3,
|
||||||
|
patient?.hospitalId,
|
||||||
|
].map((v) => normalizeText(v).toLowerCase()).filter(Boolean);
|
||||||
|
|
||||||
|
// 优先精确匹配
|
||||||
|
if (values.some((v) => v === needle)) return true;
|
||||||
|
// 兜底:包含匹配(部分医院病案号前后可能带前缀/后缀)
|
||||||
|
return values.some((v) => v.includes(needle));
|
||||||
|
}
|
||||||
|
|
||||||
|
function matchesAnyMobile(patient, q) {
|
||||||
|
const needle = normalizeDigits(q);
|
||||||
|
if (!needle) return false;
|
||||||
|
const mobiles = [
|
||||||
|
patient?.mobile,
|
||||||
|
...(Array.isArray(patient?.mobiles) ? patient.mobiles : []),
|
||||||
|
patient?.phone,
|
||||||
|
patient?.phone1,
|
||||||
|
].map(normalizeDigits).filter(Boolean);
|
||||||
|
return mobiles.some((m) => m === needle);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchList(params) {
|
||||||
|
const res = await api('searchCorpCustomerForCaseList', params);
|
||||||
|
if (!res?.success) {
|
||||||
|
throw new Error(res?.message || '搜索失败');
|
||||||
|
}
|
||||||
|
const payload =
|
||||||
|
res && typeof res === 'object'
|
||||||
|
? res.data && typeof res.data === 'object' && !Array.isArray(res.data)
|
||||||
|
? res.data
|
||||||
|
: res
|
||||||
|
: {};
|
||||||
|
const list = Array.isArray(payload.list) ? payload.list : Array.isArray(payload.data) ? payload.data : [];
|
||||||
|
return list.map(formatPatient);
|
||||||
|
}
|
||||||
|
|
||||||
// Computed
|
// Computed
|
||||||
const searchResults = computed(() => {
|
const searchResults = computed(() => {
|
||||||
return searchResultsRaw.value || [];
|
return searchResultsRaw.value || [];
|
||||||
@ -163,29 +251,58 @@ const doSearch = useDebounce(async () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const seq = (searchSeq.value += 1);
|
||||||
searching.value = true;
|
searching.value = true;
|
||||||
const res = await api('searchCorpCustomerForCaseList', {
|
try {
|
||||||
corpId,
|
if (isChinaMobile(q)) {
|
||||||
userId,
|
const digits = normalizeDigits(q);
|
||||||
teamId,
|
const list = await fetchList({
|
||||||
name: q,
|
corpId,
|
||||||
page: 1,
|
userId,
|
||||||
pageSize: 50,
|
teamId,
|
||||||
});
|
page: 1,
|
||||||
searching.value = false;
|
pageSize: 50,
|
||||||
|
mobile: digits,
|
||||||
|
});
|
||||||
|
if (seq !== searchSeq.value) return;
|
||||||
|
|
||||||
if (!res?.success) {
|
// 后端为包含匹配,这里做一次精确过滤,避免“部分号段”带来误命中
|
||||||
toast(res?.message || '搜索失败');
|
searchResultsRaw.value = list.filter((p) => matchesAnyMobile(p, digits));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLikelyArchiveNo(q)) {
|
||||||
|
const list = await fetchList({
|
||||||
|
corpId,
|
||||||
|
userId,
|
||||||
|
teamId,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 50,
|
||||||
|
archiveNo: q,
|
||||||
|
});
|
||||||
|
if (seq !== searchSeq.value) return;
|
||||||
|
|
||||||
|
// 兜底:后端字段不全时,仍然做一次本地匹配(包含 customerNumber/2/3)
|
||||||
|
searchResultsRaw.value = list.filter((p) => matchesAnyArchiveNo(p, q));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const list = await fetchList({
|
||||||
|
corpId,
|
||||||
|
userId,
|
||||||
|
teamId,
|
||||||
|
name: q,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 50,
|
||||||
|
});
|
||||||
|
if (seq !== searchSeq.value) return;
|
||||||
|
searchResultsRaw.value = list;
|
||||||
|
} catch (e) {
|
||||||
|
if (seq !== searchSeq.value) return;
|
||||||
|
toast(e?.message || '搜索失败');
|
||||||
|
} finally {
|
||||||
|
if (seq === searchSeq.value) searching.value = false;
|
||||||
}
|
}
|
||||||
const payload =
|
|
||||||
res && typeof res === 'object'
|
|
||||||
? res.data && typeof res.data === 'object' && !Array.isArray(res.data)
|
|
||||||
? res.data
|
|
||||||
: res
|
|
||||||
: {};
|
|
||||||
const list = Array.isArray(payload.list) ? payload.list : Array.isArray(payload.data) ? payload.data : [];
|
|
||||||
searchResultsRaw.value = list.map(formatPatient);
|
|
||||||
}, 600);
|
}, 600);
|
||||||
|
|
||||||
const handleSearch = () => doSearch();
|
const handleSearch = () => doSearch();
|
||||||
|
|||||||
@ -130,6 +130,7 @@ import dayjs from 'dayjs';
|
|||||||
|
|
||||||
import api from '@/utils/api';
|
import api from '@/utils/api';
|
||||||
import useAccountStore from '@/store/account';
|
import useAccountStore from '@/store/account';
|
||||||
|
import useInfoCheck from '@/hooks/useInfoCheck';
|
||||||
import { confirm as uniConfirm, hideLoading, loading as showLoading, toast } from '@/utils/widget';
|
import { confirm as uniConfirm, hideLoading, loading as showLoading, toast } from '@/utils/widget';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
@ -193,6 +194,7 @@ const currentTab = computed(() => tabs.value.find((t) => t.key === currentTabKey
|
|||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
const { account, doctorInfo } = storeToRefs(accountStore);
|
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||||
const { getDoctorInfo } = accountStore;
|
const { getDoctorInfo } = accountStore;
|
||||||
|
const { withInfo } = useInfoCheck();
|
||||||
|
|
||||||
const teamDisplay = computed(() => `${currentTeam.value?.name || ''}`);
|
const teamDisplay = computed(() => `${currentTeam.value?.name || ''}`);
|
||||||
|
|
||||||
@ -726,6 +728,10 @@ function normalizeMedicalType(raw) {
|
|||||||
const s = String(raw || '').trim();
|
const s = String(raw || '').trim();
|
||||||
if (!s) return '';
|
if (!s) return '';
|
||||||
const lower = s.toLowerCase();
|
const lower = s.toLowerCase();
|
||||||
|
// 常见后缀:xxxRecord(后端/历史数据可能返回此形式)
|
||||||
|
if (lower.endsWith('record') && s.length > 6) {
|
||||||
|
return normalizeMedicalType(s.slice(0, -6));
|
||||||
|
}
|
||||||
// 中文兜底(部分接口返回展示名)
|
// 中文兜底(部分接口返回展示名)
|
||||||
if (s.includes('门诊')) return 'outpatient';
|
if (s.includes('门诊')) return 'outpatient';
|
||||||
if (s.includes('住院') || s.includes('入院')) return 'inhospital';
|
if (s.includes('住院') || s.includes('入院')) return 'inhospital';
|
||||||
@ -1211,15 +1217,14 @@ const goToSearch = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToGroupManage = () => {
|
const goToGroupManage = withInfo(() => {
|
||||||
if (checkBatchMode()) return;
|
if (checkBatchMode()) return;
|
||||||
if (!ensureUserInfoForFeature()) return;
|
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/case/group-manage'
|
url: '/pages/case/group-manage'
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
const toggleBatchMode = () => {
|
const toggleBatchMode = withInfo(() => {
|
||||||
if (isBatchMode.value) {
|
if (isBatchMode.value) {
|
||||||
// Already in batch mode, do nothing or prompt?
|
// Already in batch mode, do nothing or prompt?
|
||||||
// Prompt says "click Other operations... prompt please finish".
|
// Prompt says "click Other operations... prompt please finish".
|
||||||
@ -1229,9 +1234,9 @@ const toggleBatchMode = () => {
|
|||||||
}
|
}
|
||||||
isBatchMode.value = true;
|
isBatchMode.value = true;
|
||||||
selectedItems.value = [];
|
selectedItems.value = [];
|
||||||
};
|
});
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = withInfo(() => {
|
||||||
if (checkBatchMode()) return;
|
if (checkBatchMode()) return;
|
||||||
const rawMax = doctorInfo.value?.maxCustomerArchive;
|
const rawMax = doctorInfo.value?.maxCustomerArchive;
|
||||||
const hasMaxField = rawMax !== undefined && rawMax !== null && String(rawMax).trim() !== '';
|
const hasMaxField = rawMax !== undefined && rawMax !== null && String(rawMax).trim() !== '';
|
||||||
@ -1303,7 +1308,7 @@ const handleCreate = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
// 新增流程:认证分支
|
// 新增流程:认证分支
|
||||||
const startVerifyFlow = () => {
|
const startVerifyFlow = () => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user