hn-hlw-pc/src/views/home/header.vue
2026-08-06 18:26:15 +08:00

321 lines
12 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>
<div common-shadow bg-fff class="header">
<div flex items-center px-15 class="w-0 flex-grow">
<img class="w-40px h-40px flex-shrink-0" :src="logoPic" />
<div color-333 font-semibold class="text-22px ml-18px max-w-1/2 truncate">
{{ corpInfo?.corp_name || "" }}
</div>
</div>
<div class="flex-shrink-0 flex items-center">
<div flex items-center class="pr-30px">
<el-dropdown v-if="needLogin">
<user-avatar flex-shrink-0 useDefault class="rounded-full mr-15px pointer" size="40"
:avatar="memberInfo.avatar" :sex="sex" />
<template #dropdown>
<el-dropdown-menu>
<template v-if="showCAMenu">
<el-dropdown-item @click="getAuthCode">
<div class="text-14px py-4px">
<span class="-ml-3px">产生激活码</span>
</div>
</el-dropdown-item>
<el-dropdown-item @click="handleOpenAutoSign">
<div class="text-14px py-4px">
<span class="-ml-3px">开启时效签</span>
</div>
</el-dropdown-item>
<el-dropdown-item @click="disableAutoSign">
<div class="text-14px py-4px">
<span class="-ml-3px">关闭时效签</span>
</div>
</el-dropdown-item>
</template>
<el-dropdown-item @click="logout">
<div class="text-14px py-4px">
<span class="-ml-3px">退出登录</span>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<user-avatar v-else flex-shrink-0 useDefault class="rounded-full mr-15px pointer" size="40"
:avatar="memberInfo.avatar" :sex="sex" />
<div>
<div class="mr-5px max-w-240px truncate text-16px font-semibold">
<span v-if="memberInfo.anotherName">{{ memberInfo.anotherName }}</span>
<ww-user v-else-if="memberInfo.userid" :openid="memberInfo.userid"></ww-user>
</div>
<el-text v-if="currentTeam && currentTeam.teamId">
<div class="inline-flex" items-center>
<span font-14 pointer color-primary class="hover:underline underline-set" @click="viewTeam">
{{ currentTeam.name }}
</span>
<span v-if="showTeams.length > 1" font-14 color-primary>({{ showTeams.length }})</span>
<el-dropdown class="switch-el-dropdown" trigger="click">
<svg-icon class="ml-4px hover:text-blue-500" pointer name="switch" size="16"></svg-icon>
<template #dropdown>
<el-dropdown-menu>
<div v-if="showTeams.length > 4" class="px-10px py-5px">
<el-input clearable v-model="teamName" size="small" placeholder="搜索团队"></el-input>
</div>
<el-scrollbar wrap-style="max-height:60vh">
<el-dropdown-item v-for="team in dropdownList" :key="team.teamId" @click="selectTeam(team)">{{
team.name }}</el-dropdown-item>
</el-scrollbar>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</el-text>
</div>
</div>
</div>
</div>
<teams-modal :team-id="currentTeam ? currentTeam.teamId : ''" :teams="showTeams" :visible="teamVisible"
@close="teamVisible = false" />
<el-dialog v-model="visible" title="机构超级管理员" :width="width" :close-on-click-modal="false" @close="close()">
<el-scrollbar wrap-class="el-dialog-body-full-scroll">
<div color-normal class="pt-10px px-10px pb-20px text-14px bg-slate-100">
<div class="leading-24px font-semibold">
超级管理员为机构自己的管理员,可以帮助使用本平台的机构员工开通账户、数据维护管理、培训支持等等服务。如您在工作中需要管理员协助的,可点击下方联系管理员。
<div class="my-5px">机构超级管理员处理事项:</div>
</div>
<div class="leading-24px">1、账户开通:包括员工基础信息维护、平台账户开通、功能权限管理。</div>
<div class="leading-24px">2、团队信息管理:团队组建管理,包括团队名称、团队介绍、团队成员、团队服务二维码的配置。</div>
<div class="leading-24px">3、基础信息数据维护:包括文章、问卷、常用语、客户来源、客户标签、机构项目、常用诊断、档案模版字段配置。</div>
<div class="leading-24px">4、客户数据管理:包括平台内客户数据的上限数管理、客户档案的删除、客户档案与团队的授权、客户档案与微信账号的解绑。</div>
</div>
<div v-loading="loading" class="p-10px">
<div color-normal class="text-16px leading-28px font-semibold">本机构超级管理员</div>
<div v-for="i in admins" :key="i.userid" class="mt-15px flex items-center">
<div class="rounded-full w-24px h-24px justify-center flex items-center bg-zinc-600 text-white">
<el-icon :size="16">
<Avatar />
</el-icon>
</div>
<div color-normal class="min-w-80px mx-10px truncate flex-shrink-0 text-16px">
<span v-if="i.anotherName">{{ i.anotherName }}</span>
<ww-user v-else :openid="i.userid"></ww-user>
</div>
<el-button v-if="memberInfo.userid !== i.userid" type="primary" size="small" @click="contact(i.userid)">联系
</el-button>
</div>
</div>
</el-scrollbar>
<template #footer>
<div text-center>
<el-button class="w-100px" @click="close">关闭</el-button>
</div>
</template>
</el-dialog>
<open-auto-sign :visible="isQrCodeDialogVisible" :qrCodeText="qrCodeText" :title="qrViewTitle"
:subTitle="qrViewSubTitle" @close="closeQr"></open-auto-sign>
</template>
<script setup>
import { computed, ref } from "vue";
import { storeToRefs } from "pinia";
import { getOpenedAccount } from "@/api/corp.js";
import { loginout } from "@/api/account.js";
import useModal from "@/hooks/useModal";
import { memberStore } from "@/store/member";
import { teamStore } from "@/store/team";
import { openChatWindow } from "@/utils/common";
import { useRouter } from "vue-router";
import UserAvatar from "@/components/user-avatar";
import SvgIcon from "@/components/svg-icon";
import TeamsModal from "./components/teams-modal.vue";
import { configStore } from "@/store/config";
import { tagsStore } from "@/store/tags";
import { ElMessageBox, ElMessage } from "element-plus";
import { useImStore } from "@/store/im";
import { doctorHasPendingOrder } from "@/api/hlw";
import openAutoSign from "@/components/ca-sign/open-auto-sign.vue";
import { caStore } from "@/components/ca-sign/store";
const logoPic = new URL("@/assets/logo.png", import.meta.url).href; // 默认logo
const qrCodeText = ref("");
const qrViewTitle = ref("");
const router = useRouter();
const needLogin = import.meta.env.VITE_NEED_LOGIN === "true"; // 是否需要登录
const { getGroups } = configStore();
const { clear } = tagsStore()
const store = teamStore();
const { setCurrentTeam } = store;
const { teams, currentTeam, allTeams, isAdmin } = storeToRefs(store);
const memberS = memberStore();
const { memberInfo, customLogo, corpInfo } = storeToRefs(memberS);
const teamVisible = ref(false);
const teamName = ref("");
const isQrCodeDialogVisible = ref(false);
const qrViewSubTitle = ref("");
const showCAMenu = computed(() => {
return (memberInfo.value.doctorNo || memberInfo.value.workNo) && import.meta.env.VITE_NEED_CA === "true"
})
async function selectTeam(team) {
await setCurrentTeam(team.teamId);
getGroups();
}
async function viewTeam() {
teamVisible.value = true;
}
const showTeams = computed(() => (isAdmin.value ? allTeams.value : teams.value));
const dropdownList = computed(() => (teamName.value.trim() ? showTeams.value.filter((item) => item.name.includes(teamName.value)) : showTeams.value));
function help() {
window.open(`https://796f-youcan-clouddev-1-8ewcqf31dbb2b5-1317294507.tcb.qcloud.la/_yiketong/${encodeURIComponent("医客通用户使用手册")}.pdf?sign=75c138d3687ad034e9d37d4d770645c0&t=1715651395`, "_blank");
}
const { close, show, visible, width } = useModal();
const admins = ref([]);
const loading = ref(false);
async function showAdmin() {
if (loading.value) return;
show();
loading.value = true;
const { data } = await getOpenedAccount();
const members = Array.isArray(data.data) ? data.data : [];
admins.value = members.filter((item) => item.roleType == "superAdmin");
loading.value = false;
}
function chat() {
if (typeof wx === "object" && wx && typeof wx.invoke === "function") {
wx.invoke("openThirdAppServiceChat");
}
}
function disableAutoSign() {
ElMessageBox.confirm("确定关闭时效签吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(async () => {
const { success, message } = await caStore().disableAutoSign();
if (success) {
ElMessage.success("关闭时效签成功");
} else {
ElMessage.error(message);
}
});
}
function contact(userid) {
openChatWindow("", "", userid);
}
async function logout() {
// return
const data = await hasPeddingOrder();
//弹出框校验
ElMessageBox.confirm(data ? "您当前还有未处理订单,确认退出吗?" : "确定退出登录吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}).then(async () => {
//确定退出登录
if (import.meta.env.VITE_NEED_IM) {
useImStore().imLogout();
};
if (sessionStorage.getItem("loginId")) {
await loginout({ loginId: sessionStorage.getItem("loginId"), userId: memberInfo.value.userid });
sessionStorage.removeItem("loginId");
}
router.replace({ name: "LOGIN", query: { corpId: sessionStorage.getItem("corpId") } });
sessionStorage.clear();
memberStore().setLogined("unlogin");
clear()
});
}
async function hasPeddingOrder() {
const res = await doctorHasPendingOrder({ doctorCode: memberInfo.value.userid });
return res.data && res.data.data === true ? true : false;
}
async function getAuthCode() {
// 产生激活码
isQrCodeDialogVisible.value = true;
qrViewTitle.value = "产生激活码";
const qrCode = await caStore().getAuthCode();
qrCodeText.value = qrCode;
qrViewSubTitle.value = "请在使用协同签名APP扫码激活";
}
function closeQr() {
isQrCodeDialogVisible.value = false;
qrCodeText.value = "";
qrViewTitle.value = "";
}
async function handleOpenAutoSign() {
// 开启时效签
const { success, message, data, caTimeRegion } = await caStore().enableAutoSign();
if (!success) {
return ElMessage.warning(message);
}
// 秒变小时 caTimeRegion
const time = Number(caTimeRegion) / 3600;
isQrCodeDialogVisible.value = true;
qrViewTitle.value = "开启时效签";
qrViewSubTitle.value = `时效签有效期为${time}小时请在有效期内使用CA证书签名`;
qrCodeText.value = data;
}
</script>
<style scoped lang="scss">
:global(.teamDialog.el-dialog .el-dialog__header) {
display: none;
}
.underline-set {
text-underline-offset: 4px;
}
.switch-el-dropdown {
outline-color: transparent !important;
outline: none !important;
}
[color-333] {
color: #333;
}
.header {
width: 100%;
height: 50px;
background: #ffffff;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #eee;
position: relative;
z-index: 9;
.left {
display: flex;
align-items: center;
.item_1 {
// width: 150px;
height: 60px;
// background: #13649b;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
padding-left: 15px;
.logo {
margin-right: 6px;
width: 40px;
height: 40px;
}
}
.name {
font-weight: 600;
color: #333;
padding-left: 12px;
font-size: 22px;
// font-style: italic;
}
}
}
</style>