2026-08-18 18:13:39 +08:00

352 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<page-loading v-if="loading && teams.length === 0" />
<full-page v-else-if="teams.length && team" class="home-container" :pageStyle="pageStyle">
<!-- <template #header> -->
<team-head :team="team" :customers="customers" :teams="teams" @changeTeam="changeTeam" />
<!-- </template> -->
<view class="home-section home-section--first">
<customer-archive ref="archiveRef" :corpId="corpId" :corpUserIds="corpUserIds"
:referenceCustomerIds="referenceCustomerIds" :team="team" @update:customers="handleCustomersUpdate" />
</view>
<view class="home-section">
<team-guide :team="team" />
</view>
<view class="home-section">
<consult ref="consultRef" :corpId="corpId" :teamId="team.teamId" :team="team" :customers="customers" />
</view>
<!-- <view class="home-section">
<team-mate :team="team" />
</view> -->
<view class="home-section">
<article-list :team="team" />
</view>
</full-page>
<yc-home v-else />
</template>
<script setup>
import { computed, ref, watch } from "vue";
import { storeToRefs } from "pinia";
import { onLoad, onShow, onShareAppMessage } from "@dcloudio/uni-app";
// import useGuard from "@/hooks/useGuard";
import useAccount from "@/store/account";
import api from "@/utils/api";
import { toast } from "@/utils/widget";
import { get, remove, set } from "@/utils/cache";
import { normalizeCorpId } from "@/utils/api-base-config";
import FullPage from "@/components/full-page.vue";
import articleList from "./article-list.vue";
import consult from "./consult.vue";
import customerArchive from "./customer-archive.vue";
import teamHead from "./team-head.vue";
import teamGuide from "./team-guide.vue";
// import teamMate from "./team-mate.vue";
import ycHome from "./yc-home.vue";
import pageLoading from "./loading.vue";
// const { useLoad, useShow } = useGuard();
const { account } = storeToRefs(useAccount());
const { login, getTeams } = useAccount();
const env = __VITE_ENV__;
const appid = env.MP_WX_APP_ID;
const shareAppVersion = env.MP_SHARE_WX_APP_VERSION;
const team = ref(null);
const teams = ref([]);
const loading = ref(false);
const customers = ref([]);
const consultRef = ref(null);
const archiveRef = ref(null);
const corpUserIds = ref({});
const referenceCustomerIds = ref({});
const pendingAction = ref(null);
const awaitingArchiveBinding = ref(false);
const HOME_CURRENT_TEAM_CACHE_KEY = "home-current-team-info";
const corpId = computed(() => team.value?.corpId);
// UI 两段式背景:顶部 281px 渐变 + 下方纯色(按 375 设计稿281px ≈ 562rpx
const pageStyle =
"background: linear-gradient(180deg, #065BD6 15.05%, #F6FAFA 95.37%) 0 0/100% 562rpx no-repeat, #F6FAFA;";
function handleCustomersUpdate(newCustomers) {
customers.value = newCustomers;
}
function getTeamIdentity(source = {}) {
return {
teamId: source.teamId || "",
corpId: normalizeCorpId(source.corpId || ""),
};
}
function cacheCurrentTeam(currentTeam) {
if (!currentTeam || !currentTeam.teamId) return;
set(HOME_CURRENT_TEAM_CACHE_KEY, getTeamIdentity(currentTeam));
}
function isSameTeam(candidate, target = {}) {
const targetTeamId = target.teamId || "";
if (!candidate || !candidate.teamId || String(candidate.teamId) !== String(targetTeamId)) return false;
const targetCorpId = normalizeCorpId(target.corpId || "");
if (!targetCorpId) return true;
const teamCorpId = normalizeCorpId(candidate.corpId || "");
return targetCorpId === teamCorpId;
}
async function changeTeam({ teamId, corpId, corpName }) {
loading.value = true;
try {
const res = await api("getTeamData", { teamId, corpId, withCorpName: true });
if (res && res.data) {
team.value = {
...res.data,
corpId: normalizeCorpId(res.data.corpId || corpId),
};
team.value.corpName = corpName || res.data.corpName || res.data.corp_name || "";
cacheCurrentTeam(team.value);
return team.value;
}
toast(res?.message || "获取团队信息失败");
return null;
} finally {
loading.value = false;
}
}
function parsePendingAction(options = {}) {
const type = options.type || "";
if (type === "experienceCoupon" && options.issueId && options.corpId) {
return {
type,
corpId: normalizeCorpId(options.corpId),
teamId: options.teamId || "",
issueId: options.issueId,
memberId: options.memberId || options.customerId || "",
couponId: options.couponId || "",
unionid: options.unionid || "",
externalUserId: options.externalUserId || "",
};
}
if (type === "appointmentRegistration" && options.customerId && options.corpId) {
return {
type,
corpId: normalizeCorpId(options.corpId),
teamId: options.teamId || "",
customerId: options.customerId,
name: options.name || "",
corpName: options.corpName || "",
appointmentId: options.appointmentId || "",
month: options.month || "",
externalUserId: options.externalUserId || "",
corpUserId: options.corpUserId || "",
};
}
return null;
}
function buildActionUrl(action) {
const params = Object.entries(action)
.filter(([key, value]) => key !== "type" && value)
.map(([key, value]) => `${key}=${encodeURIComponent(value)}`)
.join("&");
const page = action.type === "experienceCoupon"
? "/pages/experience-coupon/claim"
: "/pages/record/appointment-record";
return `${page}?${params}`;
}
function buildArchiveBindUrl(action) {
const customerId = action.memberId || action.customerId;
return [
`/pages/archive/edit-archive?corpId=${encodeURIComponent(action.corpId)}`,
`teamId=${encodeURIComponent(team.value?.teamId || action.teamId)}`,
`bindCustomerId=${encodeURIComponent(customerId)}`,
`source=${encodeURIComponent(action.type)}`,
].join("&");
}
async function syncPendingExternalUser(action) {
if (!action?.externalUserId || !account.value?.openid || !action.corpId) return;
try {
await api("syncWxappExternalUserRelation", {
corpId: action.corpId,
externalUserId: action.externalUserId,
unionid: action.unionid || account.value.unionid || "",
openid: account.value.openid,
corpUserId: action.corpUserId || "",
}, false);
} catch (error) {
console.warn("同步外部联系人关系失败", error);
}
}
async function continuePendingAction() {
const action = pendingAction.value;
if (!action || !account.value?.openid || !team.value?.teamId) return;
if (action.teamId && String(action.teamId) !== String(team.value.teamId)) {
toast("未找到目标服务团队");
pendingAction.value = null;
return;
}
await syncPendingExternalUser(action);
const customerId = action.memberId || action.customerId;
const customerRes = await api(
"getCustomerByCustomerId",
{ corpId: action.corpId, customerId },
false
);
const customer = customerRes?.data || null;
if (!customer) {
toast(customerRes?.message || "目标档案不存在");
pendingAction.value = null;
return;
}
const archiveBound = String(customer.miniAppId || "") === String(account.value.openid);
if (!archiveBound) {
if (awaitingArchiveBinding.value) {
awaitingArchiveBinding.value = false;
pendingAction.value = null;
return;
}
awaitingArchiveBinding.value = true;
uni.navigateTo({ url: buildArchiveBindUrl(action) });
return;
}
pendingAction.value = null;
awaitingArchiveBinding.value = false;
uni.navigateTo({ url: buildActionUrl(action) });
}
async function getMatchTeams(inviteTeam = null) {
loading.value = true;
try {
teams.value = await getTeams();
const inviteIdentity = typeof inviteTeam === "string" ? { teamId: inviteTeam } : (inviteTeam || {});
const cachedIdentity = get(HOME_CURRENT_TEAM_CACHE_KEY) || {};
const targetIdentity = getTeamIdentity({
teamId: inviteIdentity.teamId || team.value?.teamId || cachedIdentity.teamId,
corpId: inviteIdentity.corpId || team.value?.corpId || cachedIdentity.corpId,
});
let validTeam = teams.value.find(i => isSameTeam(i, targetIdentity));
if (pendingAction.value && targetIdentity.teamId && account.value?.openid) {
if (!validTeam) {
const bindRes = await api("bindWxappWithTeam", {
appid,
corpId: targetIdentity.corpId,
teamId: targetIdentity.teamId,
openid: account.value.openid,
});
if (!bindRes?.success) {
toast(bindRes?.message || "关联医生团队失败");
team.value = null;
return null;
}
teams.value = await getTeams();
validTeam = teams.value.find(i => isSameTeam(i, targetIdentity));
}
// 链接中的团队是本次动作的作用域,即使用户已绑定多个团队,也必须切换到该团队。
const targetTeam = await changeTeam({
...targetIdentity,
corpName: validTeam?.corpName || "",
});
if (targetTeam) {
teams.value = teams.value.length ? teams.value : [targetTeam];
return targetTeam;
}
return null;
}
const firstTeam = teams.value[0];
if (validTeam || firstTeam) {
return await changeTeam(validTeam || firstTeam);
}
team.value = null;
return null;
} finally {
loading.value = false;
}
}
// useLoad((opts) => {
// if (opts.teamId) {
// team.value = { teamId: opts.teamId, corpId: opts.corpId };
// }
// });
onLoad((options = {}) => {
pendingAction.value = parsePendingAction(options);
})
onShow(async () => {
if (!account.value) await login();
const inviteTeam = get('home-invite-team-info');
remove('home-invite-team-info');
if (inviteTeam && inviteTeam.teamId && inviteTeam.corpUserId) {
corpUserIds.value[inviteTeam.teamId] = inviteTeam.corpUserId;
}
if (inviteTeam && inviteTeam.teamId && inviteTeam.referenceCustomerId) {
referenceCustomerIds.value[inviteTeam.teamId] = inviteTeam.referenceCustomerId;
}
if (account.value && account.value.openid) {
const targetTeam = pendingAction.value?.teamId
? { teamId: pendingAction.value.teamId, corpId: pendingAction.value.corpId }
: null;
await getMatchTeams(targetTeam || (inviteTeam && inviteTeam.teamId ? inviteTeam : null));
await continuePendingAction();
} else {
teams.value = [];
}
if (consultRef.value && typeof consultRef.value.getBadgeCount === 'function') {
consultRef.value.getBadgeCount()
}
if (archiveRef.value && typeof archiveRef.value.getCustomers === 'function') {
archiveRef.value.getCustomers()
}
});
onShareAppMessage(() => {
if (team.value && team.value.supportPatientForward === 'YES') {
const customer = customers.value[0];
const referenceCustomerId = customer ? customer._id : '';
return {
title: `${team.value.name}】这个团队不错,推荐给你!`,
type: shareAppVersion || 0, // 0 正式版本 | 1 开发版本 | 2 体验版本
path: `/pages/login/redirect-page?teamId=${team.value.teamId}&corpId=${team.value.corpId}&type=archive&referenceCustomerId=${referenceCustomerId}`
}
}
})
watch(account, async (n, o) => {
if (n && !o) {
if (!pendingAction.value) await getMatchTeams();
} else if (!n && o) {
teams.value = [];
}
})
</script>
<style scoped>
.home-container {
min-height: 100vh;
}
.home-section {
margin-top: 24rpx;
}
.home-section--first {
margin-top: 0;
}
</style>