Merge remote-tracking branch 'origin/dev-wdb' into dev-hjf

This commit is contained in:
Jafeng 2026-02-05 09:24:05 +08:00
commit e6f508ca00
21 changed files with 562 additions and 343 deletions

View File

@ -216,6 +216,10 @@ page {
margin-right: 20rpx;
}
.ml-10 {
margin-left: 30rpx;
}
.ml-15 {
margin-left: 30rpx;
}

View File

@ -25,7 +25,7 @@ const props = defineProps({
}
})
const list = computed(() => props.avatarList.map(i => i || '/static/default-avatar.png'))
const list = computed(() => props.avatarList.map(i => i || '/static/default-avatar.svg'))
const size = computed(() => {
const val = Number.isInteger(props.size) && props.size > 0 ? props.size : 144;

View File

@ -41,7 +41,8 @@
{
"path": "pages/login/login",
"style": {
"navigationBarTitleText": "柚健康"
"navigationBarTitleText": "柚健康",
"navigationStyle": "custom"
}
},
{

View File

@ -31,8 +31,8 @@
</view>
<view class="px-15 py-12 flex justify-end">
<view v-if="enableHis && !customer.isConnectHis" class="mr-10 text-base text-primary">关联档案</view>
<view class="mr-10 text-base text-success" @click="changeArchive(customer)">完善个人信息</view>
<view class="mr-10 text-base text-danger" @click="unBindArchive(customer)">删除档案</view>
<view class="text-base text-success" @click="changeArchive(customer)">完善个人信息</view>
<!-- <view class="text-base text-danger" @click="unBindArchive(customer)">删除档案</view> -->
</view>
</view>
</view>

View File

@ -11,7 +11,8 @@
</view>
<template #footer>
<button-footer confirmText="保存" :showCancel="false" @confirm="confirm()" />
<button-footer :showCancel="customerId" cancelText="删除" confirmText="保存" @cancel="unBindArchive()"
@confirm="confirm()" />
</template>
</full-page>
<bind-popup :customers="customers" :corpName="corpName" :visible="visible" @close="visible = false"
@ -26,7 +27,7 @@ import dayjs from 'dayjs';
import useGuard from '@/hooks/useGuard';
import useAccount from '@/store/account';
import api from '@/utils/api';
import { toast } from '@/utils/widget';
import { toast, confirm as uniConfirm } from '@/utils/widget';
import validate from '@/utils/validate';
import ButtonFooter from '@/components/button-footer.vue';
@ -55,7 +56,12 @@ const customerArchive = ref(null);
const verifyVisible = ref(false);
const visible = ref(false);
const formData = computed(() => ({ ...customer.value, ...form.value }));
const formData = computed(() => {
if (customerId.value) {
return { ...customer.value, ...form.value }
}
return { ...customer.value, ...form.value, mobile: account.value?.mobile }
});
function change({ title, value }) {
if (title) {
@ -95,6 +101,7 @@ async function addArchive() {
loading.value = false;
const res = await api('addCustomer', { params });
if (res && res.success) {
uni.$emit('reloadTeamCustomers')
uni.redirectTo({
url: `/pages/archive/archive-result?corpId=${corpId.value}&teamId=${teamId.value}`
})
@ -154,7 +161,6 @@ async function getBaseForm() {
async function getCustomer() {
const res = await api('getCustomerByCustomerId', { customerId: customerId.value });
console.log(res.data)
if (res && res.success && res.data) {
customer.value = res.data;
} else {
@ -166,9 +172,10 @@ async function getCustomer() {
async function updateArchive() {
if (Object.keys(form.value).length > 0) {
const res = await api('updateCustomer', { id: customerId.value, ...form.value });
const res = await api('updateCustomer', { id: customerId.value, params: { ...form.value } });
if (res && res.success) {
await toast('修改成功');
uni.$emit('reloadTeamCustomers')
uni.navigateBack();
} else {
toast(res?.message || '修改失败');
@ -178,6 +185,18 @@ async function updateArchive() {
}
}
async function unBindArchive() {
await uniConfirm('确定删除档案吗?')
const res = await api('unbindMiniAppArchive', { id: customer.value._id, corpId: corpId.value, teamId: teamId.value, miniAppId: account.value.openid });
if (res && res.success) {
await toast('删除成功');
uni.$emit('reloadTeamCustomers')
uni.navigateBack();
} else {
toast(res?.message || '删除失败')
}
}
// async updateCustomer() {
// if (Object.keys(this.form).length === 0) return this.editMemberId;
// const { success, message } = await updateCustomer(
@ -194,6 +213,7 @@ onLoad(options => {
customerId.value = options.id || '';
uni.setNavigationBarTitle({ title: customerId.value ? '编辑档案' : '新增档案' })
})
useLoad(options => {
teamId.value = options.teamId;
corpId.value = options.corpId;

View File

@ -15,8 +15,7 @@
</view>
<scroll-view scroll-x="true">
<view class="flex flex-nowrap pb-5 ">
<view v-for="i in customers" :key="i._id"
class="customer-card flex-shrink-0 mr-15 relative"
<view v-for="i in customers" :key="i._id" class="customer-card flex-shrink-0 mr-15 relative"
:class="current && i._id === current._id ? 'current-customer' : ''" @click="toggle(i)">
<!-- 关系标签 -->
<view v-if="i.relationship" class="relationship-tag"
@ -28,6 +27,13 @@
:class="current && i._id === current._id ? 'text-primary' : 'text-dark'">
{{ i.name }}
</view>
<view class="flex items-center mb-5">
<image v-if="i.sex" class="sex-icon mr-5"
:src="i.sex === '男' ? '/static/home/male.svg' : '/static/home/female.svg'" />
<view class="customer-age text-base leading-normal text-gray">
{{ i.age > 0 ? i.age + '岁' : '' }}
</view>
</view>
</view>
<!-- 选中状态底部条和三角 -->
<view v-if="current && i._id === current._id" class="active-indicator">
@ -39,24 +45,25 @@
</scroll-view>
<view v-if="canAuth" class="px-10 py-5 mt-5 flex items-center bg-danger rounded-sm">
<view class="mr-5 w-0 flex-grow text-base text-white">
该档案还未授权本服务团队点击右侧授权按钮我们将更精准的为您服务
点击右侧授权按钮, 我们将更精准的为您服务
</view>
<view class="px-12 py-5 text-base rounded-sm text-dark bg-white" @click="auth()">
授权
</view>
</view>
<view v-if="current" class="flex mt-15">
<view class="info-card-new flex-grow mr-10" @click="fillBaseInfo()">
<view class="info-card-new flex-grow" @click="fillBaseInfo()">
<view class="info-bg info-bg-base"></view>
<view class="info-content">
<view class="flex items-center justify-between mb-8">
<view class="info-title">个人基本信息</view>
<image class="arrow-icon-small" src="/static/home/arrow-right-blue.png" mode="aspectFit"></image>
</view>
<view class="info-subtitle">完善个人信息</view>
<view v-if="baseInfoError" class="text-sm text-danger">请完善您的个人信息</view>
<view v-else class="info-subtitle">完善个人信息</view>
</view>
</view>
<view class="info-card-new flex-grow" @click="toHealthList()">
<view v-if="hasHealthTemp" class="ml-10 info-card-new flex-grow" @click="toHealthList()">
<view class="info-bg info-bg-health"></view>
<view class="info-content">
<view class="flex items-center justify-between mb-8">
@ -70,7 +77,7 @@
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import { storeToRefs } from 'pinia'
import useAccount from '@/store/account';
import api from '@/utils/api';
@ -104,6 +111,17 @@ const canAuth = computed(() => {
}
return false
})
const qrcode = computed(() => {
const qrcodes = props.team && Array.isArray(props.team.qrcodes) ? props.team.qrcodes : [];
return qrcodes[0] || ''
})
const hasHealthTemp = computed(() => qrcode.value && Array.isArray(qrcode.value.healthTempList) && qrcode.value.healthTempList.length > 0)
const baseInfo = computed(() => qrcode.value && qrcode.value.teamFileds && Array.isArray(qrcode.value.teamFileds.baseInfo) ? qrcode.value.teamFileds.baseInfo : [])
const baseInfoError = computed(() => {
const requiredTitles = baseInfo.value.filter(i => i.required).map(i => i.title);
return current.value && requiredTitles.some(i => !current.value[i]);
})
function fillBaseInfo() {
if (canAuth.value) {
@ -151,7 +169,6 @@ async function getCustomers() {
customers.value = res && Array.isArray(res.data) ? res.data : [];
const customer = customers.value.find(i => current.value && i._id === current.value._id);
current.value = customer || customers.value[0] || null;
// customers
emit('update:customers', customers.value);
} else {
@ -159,6 +176,10 @@ async function getCustomers() {
}
}
onMounted(() => {
uni.$on('reloadTeamCustomers', getCustomers)
})
watch(() => props.corpId, n => {
if (n) {
getCustomers()

View File

@ -1,19 +1,11 @@
<template>
<page-loading v-if="loading" />
<full-page
v-else-if="teams.length && team"
class="home-container"
:pageStyle="pageStyle"
>
<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" :teams="teams" @changeTeam="changeTeam" />
</template>
<view class="home-section home-section--first">
<customer-archive
:corpId="corpId"
:team="team"
@update:customers="handleCustomersUpdate"
/>
<customer-archive :corpId="corpId" :team="team" @update:customers="handleCustomersUpdate" />
</view>
<view class="home-section">
<consult :corpId="corpId" :teamId="team.teamId" :customers="customers" />
@ -76,7 +68,7 @@ async function changeTeam({ teamId, corpId, corpName }) {
async function getTeams() {
loading.value = true;
const res = await api("queryWxJoinedTeams", { openid: account.value.openid });
const res = await api('getWxappRelateTeams', { openid: account.value.openid });
teams.value = res && Array.isArray(res.data) ? res.data : [];
const validTeam =
teams.value.find(

View File

@ -3,70 +3,48 @@
<view :style="{ height: statusBarHeight }" class="status-bar"></view>
<view class="relative z-3 flex items-center px-15 py-12 header-bar">
<view class="flex-shrink-0 mr-5">
<group-avatar
:size="120"
:avatarList="currentTeam ? currentTeam.avatarList : []"
/>
<group-avatar :size="120" :avatarList="currentTeam ? currentTeam.avatarList : []" />
</view>
<view class="w-0 flex-grow">
<view class="flex items-center mb-10">
<view class="team-name flex-shrink-0">{{ team.name }}</view>
<view
v-if="teams.length > 1"
class="flex-shrink-0 flex items-center switch-btn ml-10"
@click="showDropDown = true"
>
<image
class="switch-icon"
src="/static/home/switch-team.png"
mode="aspectFit"
></image>
<view v-if="teams.length > 1" class="flex-shrink-0 flex items-center switch-btn ml-10"
@click="showDropDown = true">
<image class="switch-icon" src="/static/home/switch-team.png" mode="aspectFit"></image>
</view>
</view>
<view v-if="currentTeam" class="text-base text-white truncate">{{
currentTeam.corpName
}}</view>
<view v-if="currentTeam" class="text-base text-white truncate">
{{ currentTeam.corpName }}
</view>
<view
v-if="menuButtonInfo && menuButtonInfo.width > 0"
class="flex-shrink-0"
:style="{
</view>
<view v-if="menuButtonInfo && menuButtonInfo.width > 0" class="flex-shrink-0" :style="{
width: menuButtonInfo.width + 'px',
height: menuButtonInfo.height + 'px',
}"
>
}">
</view>
</view>
<view class="relative">
<view v-if="showDropDown" class="team-dropdown py-12 bg-white shadow-lg">
<scroll-view scroll-y="true" style="max-height: 50vh">
<view class="px-15">
<view
v-for="item in teams"
:key="item.teamId"
class="mb-10 p-10 flex items-center bg-gray rounded-sm"
@click="select(item)"
>
<view v-for="item in teams" :key="item.teamId" class="mb-10 p-10 flex items-center bg-gray rounded-sm"
@click="select(item)">
<view class="flex-shrink-0 mr-5 rounded-circle">
<group-avatar :size="96" :avatarList="item.avatarList" />
</view>
<view class="w-0 flex-grow mr-5">
<view class="mb-5 text-lg font-semibold text-dark">{{
item.name
}}</view>
<view class="text-base text-gray leading-normal">{{
item.corpName
}}</view>
<view class="mb-5 text-lg font-semibold text-dark">
{{ item.name }}
</view>
<view class="text-base text-gray leading-normal">
{{ item.corpName }}
</view>
</view>
<view class="flex">
<image
class="check-icon"
:src="
team && team.teamId === item.teamId
<image class="check-icon" :src="team && team.teamId === item.teamId
? '/static/form/checked.svg'
: '/static/form/unchecked.svg'
"
>
: '/static/form/uncheck.svg'
">
</image>
</view>
</view>
@ -74,20 +52,16 @@
</scroll-view>
</view>
</view>
<view v-if="team.teamTroduce" class="team-introduce-wrapper">
<view v-if="qrcode && qrcode.guide" class="team-introduce-wrapper">
<view class="team-introduce flex items-center">
<!-- 顶部小三角形 -->
<view class="triangle-wrapper">
<view class="team-triangle"></view>
</view>
<image
class="laba-icon flex-shrink-0"
src="/static/home/speaker-intro.png"
mode="aspectFit"
></image>
<view class="introduce-text flex-grow line-clamp-2">{{
team.teamTroduce
}}</view>
<image class="laba-icon flex-shrink-0" src="/static/home/speaker-intro.png" mode="aspectFit"></image>
<view class="introduce-text flex-grow line-clamp-2">
{{ qrcode.guide }}
</view>
</view>
</view>
</view>
@ -117,6 +91,10 @@ const props = defineProps({
const currentTeam = computed(() =>
props.teams.find((i) => props.team && i.teamId === props.team.teamId)
);
const qrcode = computed(() => {
const qrcodes = props.team && Array.isArray(props.team.qrcodes) ? props.team.qrcodes : [];
return qrcodes[0] || ''
})
function select(team) {
emits("changeTeam", team);
@ -195,11 +173,9 @@ onMounted(() => {
width: 690rpx;
min-height: 111rpx;
box-sizing: border-box;
background: linear-gradient(
186deg,
background: linear-gradient(186deg,
rgba(255, 255, 255, 0.4) 13.34%,
rgba(255, 255, 255, 0.6) 99.17%
);
rgba(255, 255, 255, 0.6) 99.17%);
border-radius: 16rpx;
padding: 20rpx 20rpx 20rpx 0;
position: relative;
@ -223,11 +199,9 @@ onMounted(() => {
bottom: -10rpx;
width: 16rpx;
height: 16rpx;
background: linear-gradient(
186deg,
background: linear-gradient(186deg,
rgba(255, 255, 255, 0.4) 13.34%,
rgba(255, 255, 255, 0.6) 99.17%
);
rgba(255, 255, 255, 0.6) 99.17%);
transform: translateX(-50%) rotate(45deg);
}

View File

@ -13,7 +13,7 @@
<view v-for="i in teamates" :key="i.userid"
class="member-card flex flex-shrink-0 min-w-120 mr-15 p-15"
@click="toHomePage(i)">
<image class="flex-shrink-0 avatar mr-10" :src="i.avatar || '/static/default-avatar.png'" />
<image class="flex-shrink-0 avatar mr-10" :src="i.avatar || '/static/default-avatar.svg'" />
<view class="flex-grow flex flex-col justify-between">
<view>
<view class="member-name leading-normal h-24 text-base font-semibold text-dark whitespace-nowrap">

View File

@ -1,38 +1,54 @@
<template>
<view v-if="team" class="pt-lg px-15 flex flex-col items-center text-center">
<view class="login-bg">
<image class="bg-image" src="/static/background.png" mode="aspectFill" />
<!-- 医生卡片及头像 -->
<view class="doctor-card-wrap">
<view v-if="team" class="doctor-card">
<view class="doctor-info">
<view class="doctor-name">{{ team.teamName }}</view>
<view class="doctor-hospital">{{ team.corpName }}</view>
<view class="login-tip">为您提供团队个性化专属服务</view>
</view>
</view>
<view v-else class="doctor-card doctor-card-empty">
<view class="doctor-info">
<image class="logo" src="/static/logo-plain.png" mode="aspectFill" />
<view class="doctor-name">柚健康</view>
<view class="login-tip">生命全周期健康管理伙伴</view>
</view>
</view>
<view v-if="team" class="doctor-avatar">
<group-avatar :avatarList="team.avatars" />
<view class="mt-15 text-base font-semibold text-dark">
{{ team.teamName }}
</view>
<view class="mt-12 text-sm text-gray">{{ team.corpName }}</view>
<view class="mt-15 text-lg text-dark font-semibold">为您提供团队个性化专属服务</view>
</view>
<view v-else class="pt-lg px-15 flex flex-col items-center text-center">
<image src="/static/logo-plain.png" class="logo"></image>
<view class="mt-15 text-xl font-semibold text-dark">柚健康</view>
<view class="mt-12 text-base text-dark">生命全周期健康管理伙伴</view>
</view>
<!-- 登录按钮 -->
<view class="login-btn-wrap">
<button v-if="checked" class="login-btn" type="primary" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
<button v-if="checked && account" class="login-btn" type="primary" @click="getPhoneNumber">
手机号快捷登录
</button>
<!-- <button v-if="checked" class="login-btn" type="primary" @click="getPhoneNumber()">
<button v-else-if="checked" class="login-btn" type="primary" open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber">
手机号快捷登录
</button> -->
</button>
<button v-else class="login-btn" type="primary" @click="remind()">
手机号快捷登录
</button>
</view>
<view class="flex items-center justify-center mt-12 px-15" @click="checked = !checked">
<checkbox :checked="checked" style="transform: scale(0.7)" />
<view class="text-sm text-gray">我已阅读并同意</view>
<view class="text-sm text-primary">用户协议</view>
<view class="text-sm text-primary">隐私政策</view>
<!-- 协议 -->
<view class="agreement">
<checkbox :checked="checked" @click="checked = !checked" />
<text>我已阅读并同意</text>
<text class="link" @click="openUserAgreement">用户协议</text>
<text></text>
<text class="link" @click="openPrivacyPolicy">隐私政策</text>
</view>
</view>
</template>
<script setup>
import { ref } from "vue";
import { storeToRefs } from "pinia";
import { onLoad } from "@dcloudio/uni-app";
import useAccountStore from "@/store/account";
import api from '@/utils/api';
@ -41,10 +57,12 @@ import { toast } from "@/utils/widget";
import groupAvatar from "@/components/group-avatar.vue";
const env = __VITE_ENV__;
const appid = env.MP_WX_APP_ID;
const team = ref(null);
const checked = ref(false);
const redirectUrl = ref("");
const { account } = storeToRefs(useAccountStore());
const { login } = useAccountStore();
function attempRedirect(url) {
@ -77,9 +95,13 @@ function toHome() {
});
}
async function checkTeamArchive(account) {
const res = await api('getWxAppCustomerCount', { miniAppId: account.openid, corpId: account.corpId, teamId: '1nYlVrNXGT173674701967643308' || team.value.teamId });
if (res && res.data > 0) {
async function bindTeam() {
const res = await api('bindWxappWithTeam', { appid, corpId: team.value.corpId, teamId: team.value.teamId, openid: account.value.openid });
if (!res || !res.success) {
return toast("关联团队失败");
}
const res1 = await api('getWxAppCustomerCount', { miniAppId: account.value.openid, corpId: account.value.corpId, teamId: team.value.teamId });
if (res1 && res1.data > 0) {
toHome();
} else {
attempToPage(redirectUrl.value)
@ -88,11 +110,13 @@ async function checkTeamArchive(account) {
async function getPhoneNumber(e) {
const phoneCode = e && e.detail && e.detail.code;
// if (e && !phoneCode) return;
if (!account.value) {
const res = await login(phoneCode);
if (res && team.value) {
checkTeamArchive(res)
} else if (res && redirectUrl.value) {
if (!res) return;
}
if (team.value) {
bindTeam(account.value)
} else if (redirectUrl.value) {
await attempToPage(redirectUrl.value);
} else if (res) {
toHome();
@ -121,11 +145,6 @@ onLoad((opts) => {
padding-top: 20vh;
}
.logo {
width: 160rpx;
height: 160rpx;
}
.login-btn-wrap {
width: 100vw;
display: flex;
@ -154,4 +173,161 @@ onLoad((opts) => {
.login-btn:active {
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
}
.login-bg {
min-height: 100vh;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.logo {
width: 180rpx;
height: 180rpx;
border-radius: 50%;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 500rpx;
z-index: 0;
}
.login-gradient {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 340rpx;
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
z-index: 0;
}
.doctor-card-wrap {
width: calc(100vw - 48rpx);
max-width: 600rpx;
margin: 0 auto;
position: relative;
margin-top: 320rpx;
}
.doctor-card {
height: 398rpx;
background: #fff;
border-radius: 24rpx;
background: linear-gradient(180deg, #dbe8ff 0%, #fff 50.25%);
box-shadow: 0 8rpx 32rpx rgba(59, 124, 255, 0.08);
padding: 100rpx 24rpx 0rpx 24rpx;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
z-index: 1;
}
.doctor-avatar {
border-radius: 16rpx;
background: #f2f2f2;
box-shadow: 0 2rpx 8rpx rgba(59, 124, 255, 0.08);
position: absolute;
left: 50%;
top: 0;
transform: translate(-50%, -50%);
border: 6rpx solid #fff;
z-index: 2;
}
.doctor-info {
display: flex;
flex-direction: column;
align-items: center;
}
.doctor-name {
font-size: 40rpx;
font-weight: 600;
color: #1d2129;
margin-top: 40rpx;
}
.doctor-hospital {
font-size: 28rpx;
color: #78808f;
font-weight: 400;
margin-top: 20rpx;
text-align: center;
}
.doctor-dept {
display: inline-block;
color: #213e80;
border-radius: 4rpx;
border: 1rpx solid #1a3e8433;
padding: 0 8rpx;
font-size: 22rpx;
font-weight: 400;
margin-top: 20rpx;
}
.login-tip {
font-size: 32rpx;
color: #000000;
font-weight: 500;
text-align: center;
margin-top: 40rpx;
}
.login-btn-wrap {
width: 100vw;
display: flex;
justify-content: center;
margin-top: 136rpx;
}
.login-btn-wrap-loading {
pointer-events: none;
}
.login-btn {
width: calc(100vw - 112rpx);
max-width: 600rpx;
height: 96rpx;
line-height: 96rpx;
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
color: #fff;
font-size: 32rpx;
border-radius: 48rpx;
font-weight: 600;
box-shadow: 0 4rpx 16rpx rgba(59, 124, 255, 0.08);
border: none;
}
.login-btn:active {
background: linear-gradient(270deg, #1b5cc8 2.26%, #0877f1 94.33%);
}
.agreement {
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
color: #b2b7c2;
font-size: 22rpx;
margin-top: 40rpx;
gap: 8rpx;
}
.link {
color: #3b7cff;
margin: 0 4rpx;
}
.agreement checkbox {
transform: scale(0.7);
vertical-align: middle;
}
</style>

View File

@ -5,13 +5,18 @@
</template>
<script setup>
import { ref } from "vue";
import { storeToRefs } from "pinia";
import { onLoad } from "@dcloudio/uni-app";
import api from "@/utils/api";
import { set } from "@/utils/cache";
import { toast } from "@/utils/widget";
import useAccountStore from "@/store/account";
const env = __VITE_ENV__;
const appid = env.MP_WX_APP_ID;
const { account } = storeToRefs(useAccountStore());
const teamId = ref("");
const corpId = ref("");
const loading = ref(false);
const team = ref(null);
@ -22,6 +27,9 @@ async function changeTeam({ teamId, corpId }) {
if (res && res.data) {
team.value = res.data;
team.value.corpName = res.data.corpName;
if (account.value) {
bindTeam()
} else {
set("invite-team-info", {
corpId: team.value.corpId,
teamId: team.value.teamId,
@ -35,11 +43,29 @@ async function changeTeam({ teamId, corpId }) {
uni.redirectTo({
url: "/pages/login/login?source=teamInvite",
});
}
} else {
toast(res?.message || "获取团队信息失败");
}
}
async function bindTeam() {
const res = await api('bindWxappWithTeam', { appid, corpId: team.value.corpId, teamId: team.value.teamId, openid: account.value.openid });
if (!res || !res.success) {
return toast("关联团队失败");
}
const res1 = await api('getWxAppCustomerCount', { miniAppId: account.value.openid, corpId: account.value.corpId, teamId: team.value.teamId });
if (res1 && res1.data > 0) {
uni.switchTab({
url: "/pages/home/home",
});
} else {
uni.redirectTo({
url: `/pages/archive/edit-archive?teamId=${team.value.teamId}&corpId=${team.value.corpId}`
})
}
}
onLoad((options) => {
const href =
typeof options.q === "string" ? decodeURIComponent(options.q) : "";

View File

@ -9,7 +9,7 @@ import useTeamStore from '@/store/team.js'
export default function useGroupAvatars() {
const groupAvatarMap = ref({}) // { groupID: [avatarUrl1, avatarUrl2, ...] }
const teamStore = useTeamStore()
const patientDefaultAvatar = '/static/default-avatar.png'
const patientDefaultAvatar = '/static/default-avatar.svg'
/**
* 获取单个群聊的头像列表

View File

@ -45,8 +45,8 @@ export default function useGroupChat(groupID) {
const member = chatMember.value[userId]
if (!member) {
// 如果找不到成员信息,根据是否为团队成员返回默认头像
// 团队成员和患者都使用 default-avatar.png
return '/static/default-avatar.png'
// 团队成员和患者都使用 default-avatar.svg
return '/static/default-avatar.svg'
}
// 如果有头像且不为空字符串,返回头像
@ -55,7 +55,7 @@ export default function useGroupChat(groupID) {
}
// 否则使用默认头像
return '/static/default-avatar.png'
return '/static/default-avatar.svg'
}
// 获取群聊信息和成员头像

View File

@ -2,7 +2,7 @@
<view v-if="member" class="flex flex-col h-full items-center justify-center">
<view class="business-card">
<view class="flex">
<image class="mr-10 avatar" :src="member.avatar || '/static/default-avatar.png'"></image>
<image class="mr-10 avatar" :src="member.avatar || '/static/default-avatar.svg'"></image>
<view class="w-0 flex-grow leading-normal">
<view class="flex items-center">
<view class="mr-5 text-lg font-semibold text-dark">{{ member.anotherName }}</view>

View File

@ -63,6 +63,8 @@
</template>
<script setup>
import { computed, ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import useAccount from "@/store/account";
import { onLoad, onShow } from '@dcloudio/uni-app';
import useJob from '@/hooks/useJob';
import api from '@/utils/api';
@ -75,6 +77,7 @@ const qrcode = ref('')
const member = ref(null);
const expand = ref(false);
const { memberJob, memberList } = useJob();
const { account } = storeToRefs(useAccount());
const corpNames = computed(() => {
const corpNames = member.value && Array.isArray(member.value.corpNames) ? member.value.corpNames : [];

View File

@ -20,7 +20,7 @@
</view>
<view v-for="i in teammate.leaders" :key="i._id" class="mt-12 flex p-10 border-primary rounded-sm"
@click="toHomePage(i.userid)">
<image class="flex-shrink-0 mr-10 avatar" :src="i.avatar || '/static/default-avatar.png'"></image>
<image class="flex-shrink-0 mr-10 avatar" :src="i.avatar || '/static/default-avatar.svg'"></image>
<view class="w-0 flex-grow leading-normal">
<view class="flex items-center justify-between">
<view class="flex-shrink-0 mr-5 view-lg text-dark font-semibold">{{ i.anotherName }}</view>
@ -45,7 +45,7 @@
</view>
<view v-for="i in teammate.members" :key="i._id" class="mt-12 flex p-10 border-primary rounded-sm"
@click="toHomePage(i.userid)">
<image class="flex-shrink-0 mr-10 avatar" :src="i.avatar || '/static/default-avatar.png'"></image>
<image class="flex-shrink-0 mr-10 avatar" :src="i.avatar || '/static/default-avatar.svg'"></image>
<view class="w-0 flex-grow leading-normal">
<view class="flex items-center justify-between">
<view class="flex-shrink-0 mr-5 view-lg text-dark font-semibold">{{ i.anotherName }}</view>
@ -83,7 +83,7 @@ const { memberJob, memberList: list } = useJob();
const memberList = computed(() => team.value && Array.isArray(team.value.memberList) ? team.value.memberList : [])
const avatarList = computed(() => memberList.value.map(i => i.avatar || '/static/default-avatar.png').filter(Boolean))
const avatarList = computed(() => memberList.value.map(i => i.avatar || '/static/default-avatar.svg').filter(Boolean))
const teammate = computed(() => {
const memberLeaderList = team.value && Array.isArray(team.value.memberLeaderList) ? team.value.memberLeaderList : [];

View File

@ -6,7 +6,7 @@ export default [
},
{
path: 'pages/login/login',
meta: { title: '柚健康' },
meta: { title: '柚健康', navigationStyle: 'custom' },
},
{
path: 'pages/login/redirect-page',

BIN
static/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -10,6 +10,8 @@ const urlsConfig = {
getTeamHealthTemplate: 'getTeamHealthTemplate',
getTeamHealthTemps: "getTeamHealthTemps",
getCorpMemberJob: "getCorpMemberJob",
bindWxappWithTeam: 'bindWxappWithTeam',
getWxappRelateTeams: 'getWxappRelateTeams',
getTeamMemberAvatarsAndName: "getTeamMemberAvatarsAndName"
},

View File

@ -144,7 +144,7 @@ function mergeConversationData(conversation, groupDetailsMap) {
name: formatConversationName(groupDetail),
// 更新头像(优先使用已有头像,避免闪动)
avatar: conversation.avatar || groupDetail.patient?.avatar || '/static/default-avatar.png'
avatar: conversation.avatar || groupDetail.patient?.avatar || '/static/default-avatar.svg'
}
}

View File

@ -2625,7 +2625,7 @@ class TimChatManager {
conversationID,
groupID,
name: patientName ? `${patientName}的问诊` : groupName || '问诊群聊',
avatar: '/static/default-avatar.png',
avatar: '/static/default-avatar.svg',
lastMessage,
lastMessageTime,
unreadCount: conversation.unreadCount || 0,
@ -2638,7 +2638,7 @@ class TimChatManager {
conversationID: conversation.conversationID,
groupID: conversation.conversationID?.replace('GROUP', '') || '',
name: '问诊群聊',
avatar: '/static/default-avatar.png',
avatar: '/static/default-avatar.svg',
lastMessage: '暂无消息',
lastMessageTime: Date.now(),
unreadCount: 0,