fix:修复团队加载失败的bug
This commit is contained in:
parent
ba1200a650
commit
49c9aca0e6
@ -2,7 +2,19 @@
|
||||
<view class="container">
|
||||
<!-- Header -->
|
||||
<view class="header">
|
||||
<view class="team-selector" @click="toggleTeamPopup">
|
||||
<picker
|
||||
v-if="useTeamPicker"
|
||||
mode="selector"
|
||||
:range="teamNameRange"
|
||||
:value="teamPickerIndex"
|
||||
@change="onTeamPickerChange"
|
||||
>
|
||||
<view class="team-selector">
|
||||
<text class="team-name">{{ teamDisplay }}</text>
|
||||
<text class="team-icon">⇌</text>
|
||||
</view>
|
||||
</picker>
|
||||
<view v-else class="team-selector" @click="toggleTeamPopup">
|
||||
<text class="team-name">{{ teamDisplay }}</text>
|
||||
<text class="team-icon">⇌</text>
|
||||
</view>
|
||||
@ -139,6 +151,10 @@ const currentTeam = ref(null);
|
||||
const currentTabKey = ref('all');
|
||||
const scrollIntoId = ref('');
|
||||
const teamGroups = ref([]);
|
||||
const useTeamPicker = computed(() => (Array.isArray(teams.value) ? teams.value.length : 0) > 6);
|
||||
const teamNameRange = computed(() => (Array.isArray(teams.value) ? teams.value.map((t) => t?.name || '') : []));
|
||||
const teamPickerIndex = ref(0);
|
||||
const suppressTabReload = ref(false);
|
||||
const tabs = computed(() => {
|
||||
const base = [
|
||||
{ key: 'all', label: '全部', kind: 'all' },
|
||||
@ -184,12 +200,18 @@ const BATCH_CUSTOMER_IDS_KEY = 'ykt_case_batch_customer_ids';
|
||||
|
||||
const page = ref(1);
|
||||
const pages = ref(0);
|
||||
const pageSize = ref(50);
|
||||
const pageSize = ref(200);
|
||||
const totalFromApi = ref(0);
|
||||
const loading = ref(false);
|
||||
const rawPatients = ref([]);
|
||||
const more = computed(() => page.value < pages.value);
|
||||
const currentTab = computed(() => tabs.value.find((t) => t.key === currentTabKey.value) || tabs.value[0]);
|
||||
const lastTeamsLoadOk = ref(true);
|
||||
const lastGroupsLoadOk = ref(true);
|
||||
const lastPatientsLoadOk = ref(true);
|
||||
const loadedGroupsTeamId = ref('');
|
||||
let enterRefreshInflight = null;
|
||||
const hasEnteredOnce = ref(false);
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
const { account, doctorInfo } = storeToRefs(accountStore);
|
||||
@ -198,10 +220,92 @@ const { withInfo } = useInfoCheck();
|
||||
|
||||
const teamDisplay = computed(() => `${currentTeam.value?.name || ''}`);
|
||||
|
||||
watch(
|
||||
[teams, currentTeam],
|
||||
() => {
|
||||
const list = Array.isArray(teams.value) ? teams.value : [];
|
||||
const tid = currentTeam.value?.teamId ? String(currentTeam.value.teamId) : '';
|
||||
const idx = tid ? list.findIndex((t) => String(t?.teamId || '') === tid) : -1;
|
||||
teamPickerIndex.value = idx >= 0 ? idx : 0;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
function asArray(value) {
|
||||
return Array.isArray(value) ? value : [];
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function getNetworkTypeSafe() {
|
||||
try {
|
||||
return await new Promise((resolve) => {
|
||||
let done = false;
|
||||
const timer = setTimeout(() => {
|
||||
if (done) return;
|
||||
done = true;
|
||||
resolve('unknown');
|
||||
}, 800);
|
||||
|
||||
uni.getNetworkType({
|
||||
success: (res) => {
|
||||
if (done) return;
|
||||
done = true;
|
||||
clearTimeout(timer);
|
||||
resolve(String(res?.networkType || 'unknown'));
|
||||
},
|
||||
fail: () => {
|
||||
if (done) return;
|
||||
done = true;
|
||||
clearTimeout(timer);
|
||||
resolve('unknown');
|
||||
},
|
||||
});
|
||||
});
|
||||
} catch {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
|
||||
function pickPageSizeByNetwork(type) {
|
||||
const t = String(type || '').toLowerCase();
|
||||
if (t === '2g') return 100;
|
||||
if (t === '3g') return 150;
|
||||
if (t === '4g') return 250;
|
||||
if (t === '5g' || t === 'wifi') return 300;
|
||||
return 200;
|
||||
}
|
||||
|
||||
async function apiWithRetry(urlId, data, showLoading = true, opts = {}) {
|
||||
const retries = Number(opts?.retries ?? 1);
|
||||
const baseDelay = Number(opts?.baseDelay ?? 350);
|
||||
const shouldRetryMessage = (msg) =>
|
||||
/timeout|timed out|超时|网络|network|fail|connect|ECONN|ENOTFOUND/i.test(String(msg || ''));
|
||||
|
||||
for (let i = 0; i <= retries; i += 1) {
|
||||
try {
|
||||
const res = await api(urlId, data, showLoading);
|
||||
if (res?.success) return res;
|
||||
const message = String(res?.message || '');
|
||||
if (i < retries && shouldRetryMessage(message)) {
|
||||
await sleep(Math.min(baseDelay * Math.pow(2, i), 1500));
|
||||
continue;
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (i < retries) {
|
||||
await sleep(Math.min(baseDelay * Math.pow(2, i), 1500));
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return { success: false, message: '请求失败' };
|
||||
}
|
||||
|
||||
function normalizeUserId(value) {
|
||||
if (value === null || value === undefined) return '';
|
||||
if (typeof value === 'object') {
|
||||
@ -661,11 +765,24 @@ async function loadGroups() {
|
||||
const teamId = getTeamId();
|
||||
if (!corpId || !teamId) return;
|
||||
const projection = { _id: 1, groupName: 1, parentGroupId: 1, sortOrder: 1 };
|
||||
const res = await api('getGroups', { corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false });
|
||||
let res;
|
||||
try {
|
||||
res = await apiWithRetry(
|
||||
'getGroups',
|
||||
{ corpId, teamId, page: 1, pageSize: 1000, projection, countGroupMember: false },
|
||||
false,
|
||||
{ retries: 1 }
|
||||
);
|
||||
} catch {
|
||||
res = null;
|
||||
}
|
||||
if (!res?.success) {
|
||||
teamGroups.value = [];
|
||||
lastGroupsLoadOk.value = false;
|
||||
if (!loadedGroupsTeamId.value || loadedGroupsTeamId.value !== teamId) teamGroups.value = [];
|
||||
return;
|
||||
}
|
||||
lastGroupsLoadOk.value = true;
|
||||
loadedGroupsTeamId.value = teamId;
|
||||
const list = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.data) ? res.data.data : [];
|
||||
teamGroups.value = sortGroupList(list);
|
||||
|
||||
@ -1012,7 +1129,7 @@ function groupByLetter(list) {
|
||||
return letters.map((letter) => ({ letter, data: map.get(letter) || [] }));
|
||||
}
|
||||
|
||||
async function loadTeams() {
|
||||
async function loadTeams(opts = {}) {
|
||||
if (!doctorInfo.value && account.value?.openid) {
|
||||
try {
|
||||
await getDoctorInfo();
|
||||
@ -1029,15 +1146,22 @@ async function loadTeams() {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await api('getTeamBymember', { corpId, corpUserId: userId });
|
||||
let res;
|
||||
try {
|
||||
res = await apiWithRetry('getTeamBymember', { corpId, corpUserId: userId }, !opts?.silent, { retries: 2 });
|
||||
} catch {
|
||||
res = null;
|
||||
}
|
||||
if (!res?.success) {
|
||||
toast(res?.message || '获取团队失败');
|
||||
lastTeamsLoadOk.value = false;
|
||||
if (!opts?.silent) toast(res?.message || '获取团队失败');
|
||||
return;
|
||||
}
|
||||
|
||||
const list = Array.isArray(res?.data) ? res.data : Array.isArray(res?.data?.data) ? res.data.data : [];
|
||||
const normalized = list.map(normalizeTeam).filter(Boolean);
|
||||
teams.value = normalized;
|
||||
lastTeamsLoadOk.value = true;
|
||||
|
||||
const saved = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY);
|
||||
const savedTeamId = saved?.teamId ? String(saved.teamId) : '';
|
||||
@ -1045,9 +1169,9 @@ async function loadTeams() {
|
||||
if (currentTeam.value) uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, currentTeam.value);
|
||||
}
|
||||
|
||||
async function reload(reset = true) {
|
||||
if (!currentTeam.value) return;
|
||||
if (loading.value) return;
|
||||
async function reload(reset = true, opts = {}) {
|
||||
if (!currentTeam.value) return false;
|
||||
if (loading.value) return false;
|
||||
|
||||
await ensureDoctorForQuery();
|
||||
const userId = getUserId();
|
||||
@ -1058,19 +1182,27 @@ async function reload(reset = true) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
const keepOnFail = Boolean(opts?.keepOnFail);
|
||||
const targetPage = reset ? 1 : page.value;
|
||||
|
||||
if (reset && !keepOnFail) {
|
||||
page.value = 1;
|
||||
rawPatients.value = [];
|
||||
pages.value = 0;
|
||||
totalFromApi.value = 0;
|
||||
}
|
||||
|
||||
if (reset) {
|
||||
const net = await getNetworkTypeSafe();
|
||||
pageSize.value = pickPageSizeByNetwork(net);
|
||||
}
|
||||
|
||||
const query = {
|
||||
corpId,
|
||||
userId,
|
||||
teamId,
|
||||
page: page.value,
|
||||
pageSize: 1000, // 按首字母排序时,一次加载更多数据以显示完整的字母分组
|
||||
page: targetPage,
|
||||
pageSize: pageSize.value, // 按首字母排序时,按网络自适应加载数量
|
||||
sortByFirstLetter: true, // 按姓名首字母排序
|
||||
};
|
||||
|
||||
@ -1086,14 +1218,24 @@ async function reload(reset = true) {
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
const res = await api('searchCorpCustomerForCaseList', query);
|
||||
loading.value = false;
|
||||
let res;
|
||||
try {
|
||||
res = await apiWithRetry('searchCorpCustomerForCaseList', query, !opts?.silent, { retries: 1 });
|
||||
} catch {
|
||||
res = null;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
if (!res?.success) {
|
||||
toast(res?.message || '获取患者列表失败');
|
||||
return;
|
||||
lastPatientsLoadOk.value = false;
|
||||
if (!opts?.silent || (rawPatients.value || []).length === 0) toast(res?.message || '获取患者列表失败');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reset) page.value = 1;
|
||||
lastPatientsLoadOk.value = true;
|
||||
|
||||
const payload =
|
||||
res && typeof res === 'object'
|
||||
? res.data && typeof res.data === 'object' && !Array.isArray(res.data)
|
||||
@ -1102,7 +1244,7 @@ async function reload(reset = true) {
|
||||
: {};
|
||||
const list = Array.isArray(payload.list) ? payload.list : Array.isArray(payload.data) ? payload.data : [];
|
||||
const next = list.map(formatPatient);
|
||||
rawPatients.value = page.value === 1 ? next : [...rawPatients.value, ...next];
|
||||
rawPatients.value = targetPage === 1 ? next : [...rawPatients.value, ...next];
|
||||
// 补齐创建人/新增人姓名(部分创建人不在当前团队成员列表中)
|
||||
void prefetchUserNamesFromPatients(next).catch(() => {});
|
||||
pages.value = Number(payload.pages || 0) || 0;
|
||||
@ -1116,6 +1258,8 @@ async function reload(reset = true) {
|
||||
totalFromApi.value ||
|
||||
0
|
||||
) || (totalFromApi.value || 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const handlePatientClick = (patient) => {
|
||||
@ -1191,8 +1335,40 @@ const scrollToLetter = (letter) => {
|
||||
scrollIntoId.value = letterToDomId(letter);
|
||||
};
|
||||
|
||||
async function applyTeamSelection(nextTeam) {
|
||||
if (!nextTeam) return;
|
||||
const nextId = String(nextTeam?.teamId || '');
|
||||
if (nextId && nextId === getTeamId()) return;
|
||||
|
||||
suppressTabReload.value = true;
|
||||
try {
|
||||
currentTeam.value = nextTeam;
|
||||
if (currentTeam.value) uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, currentTeam.value);
|
||||
currentTabKey.value = 'all';
|
||||
|
||||
await loadGroups();
|
||||
await loadTeamMembers();
|
||||
await reload(true);
|
||||
} finally {
|
||||
suppressTabReload.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function onTeamPickerChange(e) {
|
||||
const prev = teamPickerIndex.value;
|
||||
if (checkBatchMode()) {
|
||||
teamPickerIndex.value = prev;
|
||||
return;
|
||||
}
|
||||
const idx = Number(e?.detail?.value ?? prev);
|
||||
if (!Number.isFinite(idx)) return;
|
||||
teamPickerIndex.value = idx;
|
||||
await applyTeamSelection((Array.isArray(teams.value) ? teams.value : [])[idx]);
|
||||
}
|
||||
|
||||
const toggleTeamPopup = () => {
|
||||
if (checkBatchMode()) return;
|
||||
if (useTeamPicker.value) return;
|
||||
if (!teams.value.length) {
|
||||
toast('暂无可选团队');
|
||||
return;
|
||||
@ -1200,12 +1376,7 @@ const toggleTeamPopup = () => {
|
||||
uni.showActionSheet({
|
||||
itemList: teams.value.map((i) => i.name),
|
||||
success: async (res) => {
|
||||
currentTeam.value = teams.value[res.tapIndex] || teams.value[0] || null;
|
||||
if (currentTeam.value) uni.setStorageSync(CURRENT_TEAM_STORAGE_KEY, currentTeam.value);
|
||||
currentTabKey.value = 'all';
|
||||
await loadGroups();
|
||||
await loadTeamMembers();
|
||||
await reload(true);
|
||||
await applyTeamSelection(teams.value[res.tapIndex] || teams.value[0] || null);
|
||||
}
|
||||
});
|
||||
};
|
||||
@ -1432,7 +1603,6 @@ async function transferToCustomerPool(customerIds) {
|
||||
}
|
||||
toast('操作成功');
|
||||
cancelBatch();
|
||||
await reload(true);
|
||||
} catch (e) {
|
||||
toast('操作失败');
|
||||
} finally {
|
||||
@ -1495,7 +1665,6 @@ async function transferToOtherTeam(customerIds) {
|
||||
}
|
||||
toast('操作成功');
|
||||
cancelBatch();
|
||||
await reload(true);
|
||||
} catch (e) {
|
||||
toast('操作失败');
|
||||
} finally {
|
||||
@ -1536,10 +1705,12 @@ const handleShare = () => {
|
||||
uni.navigateTo({ url: '/pages/case/batch-share' });
|
||||
};
|
||||
|
||||
function loadMore() {
|
||||
async function loadMore() {
|
||||
if (!more.value || loading.value) return;
|
||||
page.value += 1;
|
||||
reload(false);
|
||||
const nextPage = page.value + 1;
|
||||
page.value = nextPage;
|
||||
const ok = await reload(false, { silent: true });
|
||||
if (!ok) page.value = nextPage - 1;
|
||||
}
|
||||
|
||||
watch(currentTeam, (t) => {
|
||||
@ -1549,6 +1720,7 @@ watch(currentTeam, (t) => {
|
||||
|
||||
watch(currentTabKey, () => {
|
||||
if (!currentTeam.value) return;
|
||||
if (suppressTabReload.value) return;
|
||||
loadTeamMembers();
|
||||
reload(true);
|
||||
});
|
||||
@ -1562,36 +1734,53 @@ function onTabClick(tab) {
|
||||
currentTabKey.value = tab.key;
|
||||
}
|
||||
|
||||
async function refreshOnEnter() {
|
||||
if (enterRefreshInflight) return enterRefreshInflight;
|
||||
|
||||
enterRefreshInflight = (async () => {
|
||||
const silent = hasEnteredOnce.value;
|
||||
let didLoadSomething = false;
|
||||
|
||||
// 低网/离线时尽量用缓存的当前团队兜底
|
||||
if (!currentTeam.value) {
|
||||
const saved = uni.getStorageSync(CURRENT_TEAM_STORAGE_KEY);
|
||||
if (saved && saved.teamId) currentTeam.value = saved;
|
||||
}
|
||||
|
||||
await loadTeams({ silent });
|
||||
if (lastTeamsLoadOk.value) didLoadSomething = true;
|
||||
if (currentTeam.value) {
|
||||
await loadGroups();
|
||||
await loadTeamMembers();
|
||||
const ok = await reload(true, { silent, keepOnFail: true });
|
||||
if (ok) didLoadSomething = true;
|
||||
}
|
||||
await refreshVerifyStatus();
|
||||
if (didLoadSomething) hasEnteredOnce.value = true;
|
||||
})().finally(() => {
|
||||
enterRefreshInflight = null;
|
||||
});
|
||||
|
||||
return enterRefreshInflight;
|
||||
}
|
||||
|
||||
onLoad(async () => {
|
||||
await loadTeams();
|
||||
if (currentTeam.value) {
|
||||
await loadGroups();
|
||||
await loadTeamMembers();
|
||||
await reload(true);
|
||||
}
|
||||
await refreshVerifyStatus();
|
||||
await refreshOnEnter();
|
||||
});
|
||||
|
||||
onShow(async () => {
|
||||
const need = uni.getStorageSync(NEED_RELOAD_STORAGE_KEY);
|
||||
if (need) {
|
||||
uni.removeStorageSync(NEED_RELOAD_STORAGE_KEY);
|
||||
await reload(true);
|
||||
// 批量操作完成后回到列表,默认退出批量态
|
||||
isBatchMode.value = false;
|
||||
selectedItems.value = [];
|
||||
}
|
||||
|
||||
const needGroups = uni.getStorageSync(GROUPS_RELOAD_KEY);
|
||||
if (needGroups) {
|
||||
uni.removeStorageSync(GROUPS_RELOAD_KEY);
|
||||
await loadGroups();
|
||||
await reload(true);
|
||||
} else {
|
||||
await loadGroups();
|
||||
}
|
||||
await loadTeamMembers();
|
||||
await refreshVerifyStatus();
|
||||
if (needGroups) uni.removeStorageSync(GROUPS_RELOAD_KEY);
|
||||
|
||||
await refreshOnEnter();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user