Merge remote-tracking branch 'origin/dev-hjf'
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<view class="flex flex-col items-center justify-center rounded overflow-hidden bg-gray border"
|
||||
<view :class="['flex', 'flex-col', 'items-center', 'justify-center', 'overflow-hidden', 'bg-gray', 'border', { 'rounded-circle': classType === 'circle' }]"
|
||||
:style="`width:${size.lg}rpx; height: ${size.lg}rpx;`" @click="reGenerate()">
|
||||
<view v-for="(item, index) in groups.list" :key="index" class="flex justify-center">
|
||||
<image v-for="(url, idx) in item" :key="idx" :src="url" :style="groups.style"></image>
|
||||
@ -17,6 +17,11 @@ const props = defineProps({
|
||||
type: Array,
|
||||
default: () => []
|
||||
// default: ()=>new Array(9).fill('https://picsum.photos/300/300')
|
||||
},
|
||||
classType: {
|
||||
type: String,
|
||||
default: 'circle',
|
||||
validator: (value) => ['circle', 'square'].includes(value)
|
||||
}
|
||||
})
|
||||
|
||||
@ -65,3 +70,8 @@ function getList(size = 9) {
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.rounded-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,28 +1,28 @@
|
||||
{
|
||||
"name" : "ykt-wxapp",
|
||||
"appid" : "__UNI__06F5B0E",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
"name": "ykt-team-wxapp",
|
||||
"appid": "__UNI__3EBDA15",
|
||||
"description": "",
|
||||
"versionName": "1.0.0",
|
||||
"versionCode": "100",
|
||||
"transformPx": false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
"app-plus": {
|
||||
"usingComponents": true,
|
||||
"nvueStyleCompiler": "uni-app",
|
||||
"compilerVersion": 3,
|
||||
"splashscreen": {
|
||||
"alwaysShowBeforeRender": true,
|
||||
"waiting": true,
|
||||
"autoclose": true,
|
||||
"delay": 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
"modules": {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
"distribute": {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"android": {
|
||||
"permissions": [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
@ -41,32 +41,32 @@
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
"ios": {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
"sdkConfigs": {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
"quickapp": {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "wx93af55767423938e",
|
||||
"setting" : {
|
||||
"urlCheck" : false
|
||||
"mp-weixin": {
|
||||
"appid": "wx93af55767423938e",
|
||||
"setting": {
|
||||
"urlCheck": false
|
||||
},
|
||||
"usingComponents" : true
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
"mp-alipay": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
"mp-baidu": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
"mp-toutiao": {
|
||||
"usingComponents": true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
"uniStatistics": {
|
||||
"enable": false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
"vueVersion": "3"
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "ykt-wxapp",
|
||||
"name": "医客通患者端",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "main.js",
|
||||
|
||||
@ -1,21 +1,22 @@
|
||||
<template>
|
||||
<view v-if="articles.length" class="mt-12 px-15 flex items-center justify-between">
|
||||
<view class="text-lg font-semibold text-dark">健康宣教</view>
|
||||
<view class="flex items-center" @click="toList()">
|
||||
<view class="mr-5 text-base text-gray">更多</view>
|
||||
<uni-icons type="right" color="#999"></uni-icons>
|
||||
<view v-if="articles.length" class="article-container">
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="module-title">健康宣教</view>
|
||||
<view class="flex items-center" @click="toList()">
|
||||
<view class="mr-5 text-base text-gray">更多</view>
|
||||
<image class="arrow-icon" src="/static/home/arrow-right-gray.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="px-15 mt-10">
|
||||
<view class="shadow-lg bg-white rounded">
|
||||
<view v-for="article in articles" :key="article._id"
|
||||
class="flex px-15 py-12 border-b border-solid border-gray-200">
|
||||
<image class="flex-shrink-0 mr-10 cover" :src="article.cover || '/static/book.svg'" />
|
||||
<view class="mt-10">
|
||||
<view v-for="(article, index) in articles" :key="article._id"
|
||||
class="article-card flex"
|
||||
:class="{'mb-15': index < articles.length - 1}">
|
||||
<image class="flex-shrink-0 cover" :src="article.cover || '/static/home/health-education.png'" mode="aspectFill" />
|
||||
<view class="w-0 flex-grow">
|
||||
<view class="text-base leading-normal font-semibold truncate mb-5">
|
||||
<view class="article-title truncate mb-10">
|
||||
{{ article.title }}
|
||||
</view>
|
||||
<view v-if="article.summary" class="text-base text-gray line-clamp-2">
|
||||
<view v-if="article.summary" class="article-summary line-clamp-2">
|
||||
{{ article.summary }}
|
||||
</view>
|
||||
</view>
|
||||
@ -63,16 +64,74 @@ watch(articleIds, n => {
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
<style scoped>
|
||||
.article-container {
|
||||
margin: 0 30rpx;
|
||||
margin-top: 24rpx;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.module-title {
|
||||
color: #000000;
|
||||
font-size: 36rpx;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.article-card {
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 8rpx 10rpx 0 rgba(60, 169, 145, 0.06);
|
||||
transition: all 0.3s;
|
||||
min-height: 188rpx;
|
||||
padding: 20rpx;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.article-card:active {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.cover {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
width: 272rpx;
|
||||
height: 151rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 20rpx;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.min-w-120 {
|
||||
min-width: 240rpx;
|
||||
.mb-15 {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.w-80 {
|
||||
width: 160rpx;
|
||||
.article-title {
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.article-summary {
|
||||
max-width: 402rpx;
|
||||
color: #666666;
|
||||
text-align: justify;
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.line-clamp-2 {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
overflow: hidden;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
1
pages/home/avatar.svg
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
@ -9,8 +9,8 @@
|
||||
:key="item.id"
|
||||
@click="handleItemClick(item)"
|
||||
>
|
||||
<view class="item-icon" :style="{ backgroundColor: item.bgColor }">
|
||||
<image :src="item.icon" class="icon-img" mode="aspectFit" />
|
||||
<view class="item-icon">
|
||||
<image :src="item.icon" class="icon-img" mode="aspectFill" />
|
||||
</view>
|
||||
<view class="item-label">{{ item.label }}</view>
|
||||
</view>
|
||||
@ -58,29 +58,25 @@ const consultItems = ref([
|
||||
{
|
||||
id: "chat",
|
||||
label: "聊天咨询",
|
||||
icon: "/static/homepage/chat-icon.png",
|
||||
bgColor: "#5DADE2",
|
||||
icon: "/static/home/chat-consult.png",
|
||||
needSelectConsultant: true,
|
||||
},
|
||||
{
|
||||
id: "education",
|
||||
label: "我的宣教",
|
||||
icon: "/static/homepage/education-icon.png",
|
||||
bgColor: "#F4D03F",
|
||||
icon: "/static/home/my-education.png",
|
||||
path: "/pages/article/article-list",
|
||||
},
|
||||
{
|
||||
id: "survey",
|
||||
label: "我的问卷",
|
||||
icon: "/static/homepage/survey-icon.png",
|
||||
bgColor: "#58D68D",
|
||||
icon: "/static/home/my-questionnaire.png",
|
||||
path: "/pages/survey/survey-list",
|
||||
},
|
||||
{
|
||||
id: "rating",
|
||||
label: "服务评价",
|
||||
icon: "/static/homepage/rating-icon.png",
|
||||
bgColor: "#5DADE2",
|
||||
icon: "/static/home/service-rating.png",
|
||||
path: "",
|
||||
},
|
||||
]);
|
||||
@ -155,41 +151,48 @@ function handleAddNewArchive() {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.consult-container {
|
||||
padding: 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin: 24rpx;
|
||||
margin: 0 30rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.consult-title {
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
font-size: 36rpx;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 32rpx;
|
||||
line-height: normal;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.consult-grid {
|
||||
height: 208rpx;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx 30rpx;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 24rpx;
|
||||
align-items: center;
|
||||
gap: 32rpx;
|
||||
box-shadow: 0 8rpx 10rpx 0 rgba(60, 169, 145, 0.06);
|
||||
}
|
||||
|
||||
.consult-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
gap: 12rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item-icon {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
border-radius: 20rpx;
|
||||
width: 80rpx;
|
||||
height: 80;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.2s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.consult-item:active .item-icon {
|
||||
@ -197,14 +200,14 @@ function handleAddNewArchive() {
|
||||
}
|
||||
|
||||
.icon-img {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
|
||||
.item-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
color: #666d76;
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<view class="px-15 py-12 mb-10 bg-white shadow-lg">
|
||||
<view class="archive-container">
|
||||
<view class="mb-10 flex items-center justify-between">
|
||||
<view class="flex-shrink-0 text-lg font-semibold truncate">
|
||||
<view class="module-title flex-shrink-0 truncate">
|
||||
成员档案
|
||||
</view>
|
||||
<view class="px-10 leading-normal border-dashed-auto text-base text-primary rounded-sm" @click="toManagePage()">
|
||||
档案管理
|
||||
<view class="flex items-center px-10 leading-normal rounded-sm" @click="toManagePage()">
|
||||
<image class="manage-icon mr-5" src="/static/home/archive-manage.png" mode="aspectFit"></image>
|
||||
<view style="font-size: 28rpx; color: #065BD6;">档案管理</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="customers.length === 0" class="flex items-center justify-center h-80 border-dashed text-dark rounded">
|
||||
@ -15,21 +16,33 @@
|
||||
<scroll-view scroll-x="true">
|
||||
<view class="flex flex-nowrap pb-5 ">
|
||||
<view v-for="i in customers" :key="i._id"
|
||||
class="flex-shrink-0 min-w-100 mr-10 p-10 rounded relative border-primary"
|
||||
:class="current && i._id === current._id ? 'bg-primary current-customer' : ''" @click="toggle(i)">
|
||||
<view class="flex justify-between mb-5">
|
||||
<view class="text-base leading-normal font-semibold whitespace-nowrap"
|
||||
:class="current && i._id === current._id ? 'text-white' : 'text-dark'">
|
||||
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"
|
||||
:class="i.relationship === '本人' ? 'tag-blue' : 'tag-green'">
|
||||
{{ i.relationship }}
|
||||
</view>
|
||||
<view class="flex flex-col items-center">
|
||||
<view class="customer-name text-lg leading-normal font-semibold whitespace-nowrap mb-8"
|
||||
:class="current && i._id === current._id ? 'text-primary' : 'text-dark'">
|
||||
{{ i.name }}
|
||||
</view>
|
||||
<view v-if="i.relationship" class="flex-shrink-0 px-5 rounded-sm border-auto text-sm leading-normal"
|
||||
:class="current && i._id === current._id ? 'text-white' : 'text-gray'">
|
||||
{{ i.relationship }}
|
||||
<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 class="text-base leading-normal h-normal"
|
||||
:class="current && i._id === current._id ? 'text-white' : 'text-gray'">
|
||||
{{ i.sex }} {{ i.age > 0 ? i.age + '岁' : '' }}
|
||||
<!-- 选中状态底部条和三角 -->
|
||||
<view v-if="current && i._id === current._id" class="active-indicator">
|
||||
<view class="active-bar"></view>
|
||||
<view class="active-triangle"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -42,24 +55,26 @@
|
||||
授权
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="current" class="flex mt-10">
|
||||
<view class="flex-grow p-10 rounded bg-gray mr-10" @click="fillBaseInfo()">
|
||||
<view class="flex items-center justify-between mb-5">
|
||||
<view class="text-lg">个人基本信息</view>
|
||||
<uni-icons color="#999" type="arrowright"></uni-icons>
|
||||
<view v-if="current" class="flex mt-15">
|
||||
<view class="info-card-new flex-grow mr-10" @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>
|
||||
<!-- <view v-if="formError.base" class="text-sm text-danger">
|
||||
请完善您的个人信息 v-else
|
||||
</view> -->
|
||||
<view class="text-base text-gray">基础信息填写</view>
|
||||
</view>
|
||||
<!-- v-if="healthTempList && healthTempList.length" -->
|
||||
<view class="flex-grow p-10 rounded bg-gray" @click="toHealthList()">
|
||||
<view class="flex items-center justify-between mb-5">
|
||||
<view class="text-lg">个人健康信息</view>
|
||||
<uni-icons color="#999" type="arrowright"></uni-icons>
|
||||
<view class="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">
|
||||
<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>
|
||||
<view class="text-base text-gray">健康信息列表</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -164,6 +179,199 @@ watch(() => props.corpId, n => {
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.archive-container {
|
||||
padding: 24rpx 30rpx;
|
||||
margin: 0 30rpx;
|
||||
background: linear-gradient(181deg, #C2DCFF 1.01%, #FFFFFF 43.31%);
|
||||
border-radius: 16rpx;
|
||||
box-shadow:
|
||||
inset 0 2rpx 0 0 rgba(255, 255, 255, 0.82),
|
||||
0 8rpx 10rpx 0 rgba(60, 169, 145, 0.06);
|
||||
}
|
||||
|
||||
.manage-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.module-title {
|
||||
color: #000000;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.customer-card {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(180deg, #FFFFFF 0%, #E6EFFB 100%);
|
||||
border-radius: 12rpx;
|
||||
border: 2rpx solid #AECAF2;
|
||||
transition: all 0.2s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.current-customer {
|
||||
background: #FFFFFF;
|
||||
border: 2rpx solid #065BD6;
|
||||
}
|
||||
|
||||
.customer-name {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.relationship-tag {
|
||||
position: absolute;
|
||||
top: -2rpx;
|
||||
right: -10rpx;
|
||||
padding: 4rpx 16rpx;
|
||||
font-size: 20rpx;
|
||||
line-height: normal;
|
||||
color: #fff;
|
||||
border-top-left-radius: 16rpx;
|
||||
border-bottom-left-radius: 16rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.relationship-tag::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -8rpx;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-right: 10rpx solid transparent;
|
||||
}
|
||||
|
||||
.tag-blue {
|
||||
background: #065BD6;
|
||||
}
|
||||
|
||||
.tag-blue::after {
|
||||
border-top: 8rpx solid #003F96;
|
||||
}
|
||||
|
||||
.tag-green {
|
||||
background: #1DBF98;
|
||||
}
|
||||
|
||||
.tag-green::after {
|
||||
border-top: 8rpx solid #0F8C6D;
|
||||
}
|
||||
|
||||
.active-indicator {
|
||||
position: absolute;
|
||||
bottom: -2rpx;
|
||||
left: -2rpx;
|
||||
right: -2rpx;
|
||||
height: 10rpx;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.active-bar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #065bd6;
|
||||
border-bottom-left-radius: 12rpx;
|
||||
border-bottom-right-radius: 12rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.active-triangle {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
background: #065BD6;
|
||||
margin-top: -8rpx;
|
||||
}
|
||||
|
||||
.customer-age {
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.mr-15 {
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.mt-15 {
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.mb-8 {
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.sex-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.info-card-new {
|
||||
position: relative;
|
||||
padding: 24rpx;
|
||||
border-radius: 16rpx;
|
||||
background: linear-gradient(115deg, #F4F9FF 14.74%, #DBEAFF 66.11%);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
overflow: hidden;
|
||||
width: 310rpx;
|
||||
height: 94rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.info-bg {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right bottom;
|
||||
background-size: cover;
|
||||
opacity: 0.95;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.info-content {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.info-bg-base {
|
||||
background-image: url('/static/home/basic-info-bg.svg');
|
||||
}
|
||||
|
||||
.info-bg-health {
|
||||
background-image: url('/static/home/health-info-bg.svg');
|
||||
}
|
||||
|
||||
|
||||
.info-title {
|
||||
color: #213E80;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.info-subtitle {
|
||||
color: #78808F;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.arrow-icon-small {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.font-medium {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.h-80 {
|
||||
height: 160rpx;
|
||||
}
|
||||
@ -176,15 +384,7 @@ watch(() => props.corpId, n => {
|
||||
min-width: 200rpx;
|
||||
}
|
||||
|
||||
.current-customer::after {
|
||||
bottom: -1px;
|
||||
left: calc(50% - 10px);
|
||||
border: 10px solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
border-bottom-color: white;
|
||||
.rounded-lg {
|
||||
border-radius: 16rpx;
|
||||
}
|
||||
</style>
|
||||
@ -1,14 +1,21 @@
|
||||
<template>
|
||||
<page-loading v-if="loading" />
|
||||
<full-page v-else-if="teams.length && team">
|
||||
<full-page v-else-if="teams.length && team" class="home-container" :pageStyle="pageStyle">
|
||||
<template #header>
|
||||
<team-head :team="team" :teams="teams" @changeTeam="changeTeam" />
|
||||
<view class="pb-10"></view>
|
||||
</template>
|
||||
<customer-archive :corpId="corpId" :team="team" @update:customers="handleCustomersUpdate" />
|
||||
<consult :corpId="corpId" :teamId="team.teamId" :customers="customers" />
|
||||
<team-mate :team="team" />
|
||||
<article-list :team="team" />
|
||||
<view class="home-section home-section--first">
|
||||
<customer-archive :corpId="corpId" :team="team" @update:customers="handleCustomersUpdate" />
|
||||
</view>
|
||||
<view class="home-section">
|
||||
<consult :corpId="corpId" :teamId="team.teamId" :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>
|
||||
@ -39,6 +46,10 @@ const customers = ref([]);
|
||||
|
||||
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;
|
||||
}
|
||||
@ -80,3 +91,16 @@ useShow(() => {
|
||||
})
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.home-container {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.home-section {
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.home-section--first {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,41 +1,72 @@
|
||||
<template>
|
||||
<view>
|
||||
<view :style="{ height: statusBarHeight }" class="bg-primary"></view>
|
||||
<view class="relative z-3 flex items-center px-15 py-12 bg-primary">
|
||||
<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 mb-10">
|
||||
<view class="w-0 flex-grow truncate text-lg font-semibold text-white">{{ team.name }}</view>
|
||||
<view v-if="teams.length > 1" class="flex-shinrk-0 flex items-center px-10 bg-white rounded-sm"
|
||||
@click="showDropDown = true">
|
||||
<view class="text-base">切换</view>
|
||||
<uni-icons type="down" size="12"></uni-icons>
|
||||
<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>
|
||||
</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>
|
||||
<view v-if="menuButtonInfo && menuButtonInfo.width > 0" class="flex-shrink-0"
|
||||
:style="{ width: menuButtonInfo.width + 'px', height: menuButtonInfo.height + 'px' }">
|
||||
<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;">
|
||||
<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 class="flex-shrink-0 mr-5">
|
||||
<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 ? '/static/form/checked.svg' : '/static/form/unchecked.svg'">
|
||||
<image
|
||||
class="check-icon"
|
||||
:src="
|
||||
team && team.teamId === item.teamId
|
||||
? '/static/form/checked.svg'
|
||||
: '/static/form/unchecked.svg'
|
||||
"
|
||||
>
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
@ -43,59 +74,182 @@
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="team.teamTroduce" class="px-15 py-12 flex bg-white border-b shadow-lg">
|
||||
<image class="laba-icon flex-shrink-0 mr-5" src="/static/laba.svg"></image>
|
||||
<view class="w-0 flex-grow text-sm text-gray leading-normal line-clamp-2">{{ team.teamTroduce }} </view>
|
||||
<view v-if="team.teamTroduce" 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>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showDropDown" class="mask" @click="showDropDown = false"></view>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, ref, onMounted, watch } from 'vue';
|
||||
import { computed, ref, onMounted, watch } from "vue";
|
||||
|
||||
import groupAvatar from '@/components/group-avatar.vue';
|
||||
import groupAvatar from "@/components/group-avatar.vue";
|
||||
|
||||
const statusBarHeight = ref('50px');
|
||||
const statusBarHeight = ref("50px");
|
||||
const menuButtonInfo = ref(null);
|
||||
const showDropDown = ref(false)
|
||||
const showDropDown = ref(false);
|
||||
|
||||
const emits = defineEmits(['changeTeam']);
|
||||
const emits = defineEmits(["changeTeam"]);
|
||||
const props = defineProps({
|
||||
team: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
default: () => ({}),
|
||||
},
|
||||
teams: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const currentTeam = computed(() => props.teams.find(i => props.team && i.teamId === props.team.teamId))
|
||||
const currentTeam = computed(() =>
|
||||
props.teams.find((i) => props.team && i.teamId === props.team.teamId)
|
||||
);
|
||||
|
||||
function select(team) {
|
||||
emits('changeTeam', team)
|
||||
showDropDown.value = false
|
||||
emits("changeTeam", team);
|
||||
showDropDown.value = false;
|
||||
}
|
||||
|
||||
watch(() => props.teams, (teams) => {
|
||||
if (teams.length && !(currentTeam.value && teams.some(i => i.teamId === currentTeam.value.teamId))) {
|
||||
emits('changeTeam', teams[0])
|
||||
watch(
|
||||
() => props.teams,
|
||||
(teams) => {
|
||||
if (
|
||||
teams.length &&
|
||||
!(
|
||||
currentTeam.value &&
|
||||
teams.some((i) => i.teamId === currentTeam.value.teamId)
|
||||
)
|
||||
) {
|
||||
emits("changeTeam", teams[0]);
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
const win = uni.getWindowInfo();
|
||||
if (win && win.statusBarHeight > 0) {
|
||||
statusBarHeight.value = win.statusBarHeight + 'px';
|
||||
statusBarHeight.value = win.statusBarHeight + "px";
|
||||
}
|
||||
menuButtonInfo.value = uni.getMenuButtonBoundingClientRect();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.status-bar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.header-bar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.laba-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
margin-left: 12rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.team-name {
|
||||
color: #ffffff;
|
||||
font-size: 36rpx;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.switch-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.switch-btn {
|
||||
padding: 4rpx;
|
||||
}
|
||||
|
||||
.ml-10 {
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.team-introduce-wrapper {
|
||||
padding: 0 30rpx;
|
||||
margin-top: 20rpx;
|
||||
margin-bottom: 30rpx;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.team-introduce {
|
||||
width: 690rpx;
|
||||
min-height: 111rpx;
|
||||
box-sizing: border-box;
|
||||
background: linear-gradient(
|
||||
186deg,
|
||||
rgba(255, 255, 255, 0.4) 13.34%,
|
||||
rgba(255, 255, 255, 0.6) 99.17%
|
||||
);
|
||||
border-radius: 16rpx;
|
||||
padding: 20rpx 20rpx 20rpx 0;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.triangle-wrapper {
|
||||
position: absolute;
|
||||
top: -12rpx;
|
||||
left: 60rpx;
|
||||
width: 24rpx;
|
||||
height: 12rpx;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.team-triangle {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -10rpx;
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
background: linear-gradient(
|
||||
186deg,
|
||||
rgba(255, 255, 255, 0.4) 13.34%,
|
||||
rgba(255, 255, 255, 0.6) 99.17%
|
||||
);
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
}
|
||||
|
||||
.introduce-text {
|
||||
max-width: 594rpx;
|
||||
color: #000000;
|
||||
font-size: 24rpx;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.line-clamp-2 {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.leading-relaxed {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
@ -105,7 +259,7 @@ onMounted(() => {
|
||||
|
||||
.mask {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
z-index: 99;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@ -114,7 +268,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.z-3 {
|
||||
z-index: 3;
|
||||
z-index: 101;
|
||||
}
|
||||
|
||||
.team-dropdown {
|
||||
@ -122,8 +276,12 @@ onMounted(() => {
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
z-index: 100;
|
||||
border-bottom-left-radius: 16rpx;
|
||||
border-bottom-right-radius: 16rpx;
|
||||
}
|
||||
|
||||
.rounded-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
</style>
|
||||
@ -1,33 +1,37 @@
|
||||
<template>
|
||||
<view class="mt-12 px-15 flex items-center justify-between">
|
||||
<view class="text-lg font-semibold text-dark">团队成员</view>
|
||||
<view class="flex items-center" @click="toTeamDetail()">
|
||||
<view class="mr-5 text-base text-gray">团队详情</view>
|
||||
<uni-icons type="right" color="#999"></uni-icons>
|
||||
<view class="team-mate-container">
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="module-title">团队成员</view>
|
||||
<view class="flex items-center" @click="toTeamDetail()">
|
||||
<view class="mr-5 text-base text-gray">团队详情</view>
|
||||
<image class="arrow-icon" src="/static/home/arrow-right-gray.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="px-15 mt-10">
|
||||
<scroll-view scroll-x="true">
|
||||
<view class="flex flex-nowrap pb-5 border-b">
|
||||
<view v-for="i in teamates" :key="i.userid"
|
||||
class="flex flex-shrink-0 min-w-120 p-10 mr-10 rounded-sm border-auto text-primary bg-white"
|
||||
@click="toHomePage(i)">
|
||||
<image class="flex-shrink-0 avatar mr-5" :src="i.avatar || '/static/default-avatar.png'" />
|
||||
<view class="flex-grow flex flex-col">
|
||||
<view class="leading-normal h-24 text-lg font-semibold text-dark whitespace-nowrap">
|
||||
{{ i.anotherName }}
|
||||
</view>
|
||||
<view class="max-w-100 h-21 leading-normal text-base text-gray truncate">
|
||||
{{ memberJob[i.userid] }}
|
||||
</view>
|
||||
<view v-if="i.canAddFriend" class="w-80 text-base leading-none border text-center text-dark rounded-full"
|
||||
@click.stop="toQrcode(i)">
|
||||
添加好友
|
||||
<view class="mt-10">
|
||||
<scroll-view scroll-x="true">
|
||||
<view class="flex flex-nowrap pb-5">
|
||||
<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'" />
|
||||
<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">
|
||||
{{ i.anotherName }}
|
||||
</view>
|
||||
<view class="member-job max-w-100 h-21 leading-normal text-sm text-gray truncate">
|
||||
{{ memberJob[i.userid] }}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="i.canAddFriend" class="add-friend-btn text-sm leading-none text-center text-primary"
|
||||
@click.stop="toQrcode(i)">
|
||||
添加好友
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup>
|
||||
@ -67,28 +71,85 @@ watch(teamates, val => {
|
||||
|
||||
</script>
|
||||
<style scoped>
|
||||
.team-mate-container {
|
||||
margin: 0 30rpx;
|
||||
margin-top: 24rpx;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
|
||||
.member-card {
|
||||
background: white;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
.member-card:active {
|
||||
transform: translateY(-2rpx);
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 120rpx;
|
||||
height: 128rpx;
|
||||
border-radius: 12rpx;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.add-friend-btn {
|
||||
width: 128rpx;
|
||||
height: 48rpx;
|
||||
line-height: 48rpx;
|
||||
padding: 0;
|
||||
background: rgba(6, 91, 214, 0.10);
|
||||
color: #065BD6;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 10rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.module-title {
|
||||
color: #000000;
|
||||
font-size: 36rpx;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.member-job {
|
||||
color: #999999;
|
||||
font-size: 24rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.member-name {
|
||||
color: #333333;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.h-24 {
|
||||
height: 48rpx;
|
||||
min-height: 48rpx;
|
||||
}
|
||||
|
||||
.h-21 {
|
||||
height: 42rpx;
|
||||
min-height: 42rpx;
|
||||
}
|
||||
|
||||
.min-w-120 {
|
||||
min-width: 240rpx;
|
||||
min-width: 260rpx;
|
||||
}
|
||||
|
||||
.max-w-100 {
|
||||
max-width: 200rpx;
|
||||
}
|
||||
|
||||
.w-80 {
|
||||
width: 160rpx;
|
||||
.mr-15 {
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
</style>
|
||||
@ -16,6 +16,101 @@ $primary-color: #0877F1;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* 患者信息栏样式 */
|
||||
.patient-info-bar {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
padding: 20rpx 32rpx;
|
||||
z-index: 10;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.patient-info-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.patient-basic-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.patient-name {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 200rpx;
|
||||
}
|
||||
|
||||
.patient-detail {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.badge-text {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.badge-pending {
|
||||
background: #fff3cd;
|
||||
|
||||
.badge-text {
|
||||
color: #856404;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-processing {
|
||||
background: #d1ecf1;
|
||||
|
||||
.badge-text {
|
||||
color: #0c5460;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-finished {
|
||||
background: #d4edda;
|
||||
|
||||
.badge-text {
|
||||
color: #155724;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-cancelled {
|
||||
background: #f8d7da;
|
||||
|
||||
.badge-text {
|
||||
color: #721c24;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-rejected {
|
||||
background: #f8d7da;
|
||||
|
||||
.badge-text {
|
||||
color: #721c24;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
@ -348,7 +443,7 @@ $primary-color: #0877F1;
|
||||
.text-input,
|
||||
.voice-input-btn {
|
||||
flex: 1;
|
||||
padding: 16rpx 46rpx;
|
||||
padding: 26rpx 46rpx;
|
||||
background-color: #f3f5fa;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 16rpx;
|
||||
@ -931,7 +1026,7 @@ $primary-color: #0877F1;
|
||||
.text-input::-moz-placeholder,
|
||||
.text-input:-ms-input-placeholder,
|
||||
.text-input::placeholder {
|
||||
line-height: normal;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.voice-input-btn::-webkit-input-placeholder,
|
||||
|
||||
107
pages/message/hooks/use-group-avatars.js
Normal file
@ -0,0 +1,107 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import api from '@/utils/api.js'
|
||||
import useTeamStore from '@/store/team.js'
|
||||
|
||||
/**
|
||||
* 群聊头像管理hook - 为消息列表中的每个群聊获取成员头像
|
||||
* 用于在消息列表中显示群聊的group-avatar组件
|
||||
*/
|
||||
export default function useGroupAvatars() {
|
||||
const groupAvatarMap = ref({}) // { groupID: [avatarUrl1, avatarUrl2, ...] }
|
||||
const teamStore = useTeamStore()
|
||||
const patientDefaultAvatar = '/static/default-avatar.png'
|
||||
|
||||
/**
|
||||
* 获取单个群聊的头像列表
|
||||
* @param {string} groupID 群组ID
|
||||
* @param {string} teamId 团队ID
|
||||
* @param {string} patientId 患者ID
|
||||
* @returns {Promise<Array>} 头像URL数组
|
||||
*/
|
||||
async function getGroupAvatarList(groupID, teamId, patientId) {
|
||||
try {
|
||||
if (!teamId) {
|
||||
console.warn(`群聊 ${groupID} 没有 teamId,无法获取头像`)
|
||||
return [patientDefaultAvatar]
|
||||
}
|
||||
|
||||
// 获取团队成员的头像和名称
|
||||
const memberMap = await teamStore.getTeamMemberAvatarsAndName(teamId)
|
||||
|
||||
if (!memberMap || Object.keys(memberMap).length === 0) {
|
||||
console.warn(`群聊 ${groupID} 的团队成员为空`)
|
||||
return [patientDefaultAvatar]
|
||||
}
|
||||
|
||||
// 提取头像列表(过滤掉空头像,使用默认头像替代)
|
||||
const avatarList = Object.values(memberMap)
|
||||
.map(member => {
|
||||
// 如果成员有头像且不为空,使用成员头像;否则使用默认头像
|
||||
return (member.avatar && member.avatar.trim() !== '')
|
||||
? member.avatar
|
||||
: patientDefaultAvatar
|
||||
})
|
||||
|
||||
// 添加患者默认头像
|
||||
avatarList.push(patientDefaultAvatar)
|
||||
|
||||
console.log(`群聊 ${groupID} 的头像列表已加载,共 ${avatarList.length} 个头像`)
|
||||
return avatarList
|
||||
} catch (error) {
|
||||
console.error(`获取群聊 ${groupID} 的头像列表失败:`, error)
|
||||
return [patientDefaultAvatar]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量获取多个群聊的头像列表
|
||||
* @param {Array} conversationList 会话列表
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function loadGroupAvatars(conversationList) {
|
||||
if (!conversationList || conversationList.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
// 并发加载所有群聊的头像
|
||||
const promises = conversationList.map(async (conversation) => {
|
||||
const avatarList = await getGroupAvatarList(
|
||||
conversation.groupID,
|
||||
conversation.teamId,
|
||||
conversation.patientId
|
||||
)
|
||||
groupAvatarMap.value[conversation.groupID] = avatarList
|
||||
})
|
||||
|
||||
await Promise.all(promises)
|
||||
console.log('所有群聊头像加载完成')
|
||||
} catch (error) {
|
||||
console.error('批量加载群聊头像失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定群聊的头像列表
|
||||
* @param {string} groupID 群组ID
|
||||
* @returns {Array} 头像URL数组
|
||||
*/
|
||||
function getAvatarList(groupID) {
|
||||
return groupAvatarMap.value[groupID] || [patientDefaultAvatar]
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
*/
|
||||
function clearCache() {
|
||||
groupAvatarMap.value = {}
|
||||
}
|
||||
|
||||
return {
|
||||
groupAvatarMap,
|
||||
getGroupAvatarList,
|
||||
loadGroupAvatars,
|
||||
getAvatarList,
|
||||
clearCache
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,18 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { onShow, onUnload } from '@dcloudio/uni-app'
|
||||
import api from '@/utils/api.js'
|
||||
import useTeamStore from '@/store/team.js'
|
||||
|
||||
/**
|
||||
* 简单的群聊hook
|
||||
* 群聊hook - 管理群聊成员和头像
|
||||
* @param {string} groupID 群组ID
|
||||
*/
|
||||
export default function useGroupChat(groupID) {
|
||||
const groupInfo = ref({})
|
||||
const members = ref([])
|
||||
const teamMemberIds = ref([]) // 存储团队成员的userId列表
|
||||
const patientId = ref('') // 存储患者ID
|
||||
const teamStore = useTeamStore()
|
||||
|
||||
// 群聊成员映射
|
||||
const chatMember = computed(() => {
|
||||
@ -15,30 +20,92 @@ export default function useGroupChat(groupID) {
|
||||
members.value.forEach(member => {
|
||||
res[member.id] = {
|
||||
name: member.name,
|
||||
avatar: member.avatar || '/static/default-avatar.png'
|
||||
avatar: member.avatar,
|
||||
isTeamMember: member.isTeamMember // 标记是否为团队成员
|
||||
}
|
||||
// 如果成员有 miniAppId(患者的聊天 userID),也添加一个映射(用于消息的 from 字段)
|
||||
if (member.miniAppId) {
|
||||
res[member.miniAppId] = {
|
||||
name: member.name,
|
||||
avatar: member.avatar,
|
||||
isTeamMember: member.isTeamMember
|
||||
}
|
||||
}
|
||||
})
|
||||
return res
|
||||
})
|
||||
|
||||
// 获取群聊信息
|
||||
// 判断某个userId是否为团队成员
|
||||
const isTeamMember = (userId) => {
|
||||
return teamMemberIds.value.includes(userId)
|
||||
}
|
||||
|
||||
// 获取用户头像(根据是否为团队成员返回不同的默认头像)
|
||||
const getUserAvatar = (userId) => {
|
||||
const member = chatMember.value[userId]
|
||||
if (!member) {
|
||||
// 如果找不到成员信息,根据是否为团队成员返回默认头像
|
||||
// 团队成员和患者都使用 default-avatar.png
|
||||
return '/static/default-avatar.png'
|
||||
}
|
||||
|
||||
// 如果有头像且不为空字符串,返回头像
|
||||
if (member.avatar && member.avatar.trim() !== '') {
|
||||
return member.avatar
|
||||
}
|
||||
|
||||
// 否则使用默认头像
|
||||
return '/static/default-avatar.png'
|
||||
}
|
||||
|
||||
// 获取群聊信息和成员头像
|
||||
async function getGroupInfo() {
|
||||
const gid = typeof groupID === 'string' ? groupID : groupID.value
|
||||
if (!gid) return
|
||||
|
||||
try {
|
||||
// 这里可以调用API获取群聊信息
|
||||
// const res = await getGroupDetail(gid)
|
||||
// if (res && res.success) {
|
||||
// groupInfo.value = res.data
|
||||
// members.value = res.data.members || []
|
||||
// }
|
||||
// 1. 获取群聊基本信息
|
||||
const groupResult = await api('getGroupListByGroupId', { groupId: gid })
|
||||
|
||||
// 暂时使用本地数据
|
||||
groupInfo.value = {
|
||||
groupID: gid,
|
||||
name: '群聊',
|
||||
status: 'active'
|
||||
if (groupResult && groupResult.success && groupResult.data) {
|
||||
groupInfo.value = {
|
||||
groupID: gid,
|
||||
name: groupResult.data.team?.name || '群聊',
|
||||
status: groupResult.data.orderStatus || 'active',
|
||||
teamId: groupResult.data.teamId
|
||||
}
|
||||
|
||||
// 2. 如果有teamId,获取团队成员头像和名称
|
||||
if (groupResult.data.teamId) {
|
||||
const memberMap = await teamStore.getTeamMemberAvatarsAndName(groupResult.data.teamId)
|
||||
|
||||
// 3. 存储团队成员ID列表
|
||||
teamMemberIds.value = Object.keys(memberMap)
|
||||
|
||||
// 4. 构建团队成员列表(从返回的 { userId: { avatar, name } } 中提取)
|
||||
members.value = teamMemberIds.value.map(userId => {
|
||||
const memberInfo = memberMap[userId] || {}
|
||||
return {
|
||||
id: userId,
|
||||
name: memberInfo.name || userId, // 使用返回的 name,如果没有则用 userId
|
||||
avatar: memberInfo.avatar || '', // 使用返回的 avatar
|
||||
isTeamMember: true
|
||||
}
|
||||
})
|
||||
|
||||
// 5. 添加患者信息(使用默认患者头像)
|
||||
if (groupResult.data.patient) {
|
||||
const pid = groupResult.data.patientId?.toString() || ''
|
||||
patientId.value = pid
|
||||
members.value.push({
|
||||
id: pid,
|
||||
name: groupResult.data.patient.name || '患者',
|
||||
avatar: '', // 患者不设置头像,使用默认
|
||||
isTeamMember: false,
|
||||
miniAppId: groupResult.data.patient.miniAppId || '' // 患者的聊天 userID
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取群聊信息失败:', error)
|
||||
@ -57,6 +124,8 @@ export default function useGroupChat(groupID) {
|
||||
groupInfo,
|
||||
members,
|
||||
chatMember,
|
||||
getGroupInfo
|
||||
getGroupInfo,
|
||||
isTeamMember,
|
||||
getUserAvatar
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,20 @@
|
||||
<template>
|
||||
<view class="chat-page">
|
||||
<!-- 患者信息栏 -->
|
||||
<view class="patient-info-bar" v-if="patientInfo.name">
|
||||
<view class="patient-info-content">
|
||||
<view class="patient-basic-info">
|
||||
<text class="patient-name">{{ patientInfo.name }}</text>
|
||||
<text class="patient-detail"
|
||||
>{{ patientInfo.sex }} · {{ patientInfo.age }}岁</text
|
||||
>
|
||||
</view>
|
||||
<view class="status-badge" :class="chatStatusInfo.badgeClass" v-if="chatStatusInfo.badgeText">
|
||||
<text class="badge-text">{{ chatStatusInfo.badgeText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 聊天消息区域 -->
|
||||
<scroll-view
|
||||
class="chat-content"
|
||||
@ -50,23 +65,19 @@
|
||||
|
||||
<!-- 消息内容 -->
|
||||
<view v-else class="message-content">
|
||||
<!-- 医生头像(左侧) -->
|
||||
<!-- 发送者头像(统一处理) -->
|
||||
<image
|
||||
v-if="message.flow === 'in'"
|
||||
class="doctor-msg-avatar"
|
||||
:src="
|
||||
chatMember[message.from]?.avatar || '/static/default-avatar.png'
|
||||
"
|
||||
:src="getUserAvatar(message.from)"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
|
||||
<!-- 患者头像(右侧) -->
|
||||
<!-- 发送者头像(统一处理) -->
|
||||
<image
|
||||
v-if="message.flow === 'out'"
|
||||
class="user-msg-avatar"
|
||||
:src="
|
||||
chatMember[message.from]?.avatar || '/static/home/avatar.svg'
|
||||
"
|
||||
:src="getUserAvatar(message.from)"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
|
||||
@ -180,12 +191,12 @@ const { initIMAfterLogin } = useAccountStore();
|
||||
const chatInputRef = ref(null);
|
||||
|
||||
const groupId = ref("");
|
||||
const { chatMember, getGroupInfo } = useGroupChat(groupId);
|
||||
const { chatMember, getGroupInfo, getUserAvatar } = useGroupChat(groupId);
|
||||
|
||||
// 动态设置导航栏标题
|
||||
const updateNavigationTitle = () => {
|
||||
const updateNavigationTitle = (title = "群聊") => {
|
||||
uni.setNavigationBarTitle({
|
||||
title: "群聊",
|
||||
title: title,
|
||||
});
|
||||
};
|
||||
|
||||
@ -202,6 +213,26 @@ const isEvaluationPopupOpen = ref(false);
|
||||
// 订单状态
|
||||
const orderStatus = ref("");
|
||||
|
||||
// 患者信息
|
||||
const patientInfo = ref({
|
||||
name: "",
|
||||
sex: "",
|
||||
age: "",
|
||||
mobile: "",
|
||||
});
|
||||
|
||||
// 患者ID
|
||||
const patientId = ref("");
|
||||
|
||||
// 聊天状态信息
|
||||
const chatStatusInfo = ref({
|
||||
show: false,
|
||||
title: "",
|
||||
detail: "",
|
||||
badgeText: "",
|
||||
badgeClass: "",
|
||||
});
|
||||
|
||||
// 计算弹框显示状态
|
||||
const showConsultCancel = computed(() => orderStatus.value === "pending");
|
||||
const showConsultApply = computed(
|
||||
@ -258,9 +289,33 @@ const fetchGroupOrderStatus = async () => {
|
||||
if (result.success && result.data) {
|
||||
orderStatus.value = result.data.orderStatus || "";
|
||||
corpId.value = result.data.corpId || "";
|
||||
|
||||
// 更新导航栏标题为团队名称
|
||||
const teamName = result.data.team?.name || "群聊";
|
||||
updateNavigationTitle(teamName);
|
||||
|
||||
// 更新患者信息
|
||||
if (result.data.patient) {
|
||||
patientInfo.value = {
|
||||
name: result.data.patient.name || "",
|
||||
sex: result.data.patient.sex || "",
|
||||
age: result.data.patient.age || "",
|
||||
mobile: result.data.patient.mobile || "",
|
||||
};
|
||||
}
|
||||
// 更新患者ID
|
||||
if (result.data.patientId) {
|
||||
patientId.value = result.data.patientId.toString();
|
||||
}
|
||||
|
||||
// 更新聊天状态栏信息
|
||||
updateChatStatusInfo(result.data);
|
||||
|
||||
console.log("获取群组订单状态:", {
|
||||
orderStatus: orderStatus.value,
|
||||
corpId: corpId.value,
|
||||
teamName: teamName,
|
||||
patientInfo: patientInfo.value,
|
||||
});
|
||||
} else {
|
||||
console.error("获取群组订单状态失败:", result.message);
|
||||
@ -270,7 +325,72 @@ const fetchGroupOrderStatus = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 处理接收到的系统消息
|
||||
// 更新聊天状态栏信息
|
||||
const updateChatStatusInfo = (groupData) => {
|
||||
const status = groupData.orderStatus || "";
|
||||
|
||||
let statusConfig = {
|
||||
show: false,
|
||||
title: "",
|
||||
detail: "",
|
||||
badgeText: "",
|
||||
badgeClass: "",
|
||||
};
|
||||
|
||||
switch (status) {
|
||||
case "pending":
|
||||
statusConfig = {
|
||||
show: true,
|
||||
title: "等待医生接受",
|
||||
detail: "您的咨询申请已提交",
|
||||
badgeText: "待处理",
|
||||
badgeClass: "badge-pending",
|
||||
};
|
||||
break;
|
||||
case "processing":
|
||||
statusConfig = {
|
||||
show: true,
|
||||
title: "咨询进行中",
|
||||
detail: "医生正在为您服务",
|
||||
badgeText: "进行中",
|
||||
badgeClass: "badge-processing",
|
||||
};
|
||||
break;
|
||||
case "finished":
|
||||
statusConfig = {
|
||||
show: true,
|
||||
title: "咨询已完成",
|
||||
detail: "感谢您的咨询",
|
||||
badgeText: "已完成",
|
||||
badgeClass: "badge-finished",
|
||||
};
|
||||
break;
|
||||
case "cancelled":
|
||||
statusConfig = {
|
||||
show: true,
|
||||
title: "咨询已取消",
|
||||
detail: "您已取消此次咨询",
|
||||
badgeText: "已取消",
|
||||
badgeClass: "badge-cancelled",
|
||||
};
|
||||
break;
|
||||
case "rejected":
|
||||
statusConfig = {
|
||||
show: true,
|
||||
title: "咨询已拒绝",
|
||||
detail: "医生已拒绝您的咨询申请",
|
||||
badgeText: "已拒绝",
|
||||
badgeClass: "badge-rejected",
|
||||
};
|
||||
break;
|
||||
default:
|
||||
statusConfig.show = false;
|
||||
}
|
||||
|
||||
chatStatusInfo.value = statusConfig;
|
||||
};
|
||||
|
||||
// 处理系统消息接收
|
||||
function handleSystemMessageReceived(message) {
|
||||
try {
|
||||
if (!message.payload?.data) return;
|
||||
@ -696,7 +816,7 @@ const handleScrollToUpper = async () => {
|
||||
onShow(() => {
|
||||
if (!account.value || !openid.value) {
|
||||
uni.redirectTo({
|
||||
url: "/pages-center/login/login",
|
||||
url: "/pages/login/login",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -24,10 +24,10 @@
|
||||
@click="handleClickConversation(conversation)"
|
||||
>
|
||||
<view class="avatar-container">
|
||||
<image
|
||||
class="avatar"
|
||||
:src="conversation.avatar || '/static/default-avatar.png'"
|
||||
mode="aspectFill"
|
||||
<GroupAvatar
|
||||
:avatarList="getAvatarList(conversation.groupID)"
|
||||
:size="96"
|
||||
classType="square"
|
||||
/>
|
||||
<view v-if="conversation.unreadCount > 0" class="unread-badge">
|
||||
<text class="unread-text">{{
|
||||
@ -81,6 +81,8 @@ import { storeToRefs } from "pinia";
|
||||
import useAccountStore from "@/store/account.js";
|
||||
import { globalTimChatManager } from "@/utils/tim-chat.js";
|
||||
import { mergeConversationWithGroupDetails } from "@/utils/conversation-merger.js";
|
||||
import useGroupAvatars from "./hooks/use-group-avatars.js";
|
||||
import GroupAvatar from "@/components/group-avatar.vue";
|
||||
|
||||
// 获取登录状态
|
||||
const { account, openid, isIMInitialized } = storeToRefs(useAccountStore());
|
||||
@ -93,6 +95,9 @@ const loadingMore = ref(false);
|
||||
const hasMore = ref(false);
|
||||
const refreshing = ref(false);
|
||||
|
||||
// 群聊头像管理
|
||||
const { loadGroupAvatars, getAvatarList } = useGroupAvatars();
|
||||
|
||||
// 初始化IM
|
||||
const initIM = async () => {
|
||||
console.log("=== message.vue initIM 开始 ===");
|
||||
@ -184,7 +189,14 @@ const loadConversationList = async () => {
|
||||
conversationList.value = await mergeConversationWithGroupDetails(
|
||||
result.groupList
|
||||
);
|
||||
console.log("群聊列表加载成功,共", conversationList.value, "个会话");
|
||||
console.log(
|
||||
"群聊列表加载成功,共",
|
||||
conversationList.value.length,
|
||||
"个会话"
|
||||
);
|
||||
|
||||
// 加载所有群聊的头像
|
||||
await loadGroupAvatars(conversationList.value);
|
||||
} else {
|
||||
console.error("加载群聊列表失败:", result);
|
||||
uni.showToast({
|
||||
@ -291,7 +303,10 @@ const setupConversationListener = () => {
|
||||
// 保持原有头像,避免闪动
|
||||
avatar: existing.avatar || conversationData.avatar,
|
||||
// 保留较大的未读数(避免被后端数据覆盖)
|
||||
unreadCount: Math.max(existing.unreadCount || 0, conversationData.unreadCount || 0)
|
||||
unreadCount: Math.max(
|
||||
existing.unreadCount || 0,
|
||||
conversationData.unreadCount || 0
|
||||
),
|
||||
};
|
||||
needSort = true;
|
||||
console.log(
|
||||
@ -331,11 +346,11 @@ const setupConversationListener = () => {
|
||||
// 检查当前页面栈,判断用户是否正在查看该会话的聊天详情页
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
|
||||
|
||||
// 获取当前页面的 groupID 参数(如果在聊天详情页)
|
||||
const currentGroupID = currentPage?.options?.groupID;
|
||||
const isViewingThisConversation =
|
||||
currentPage?.route === "pages/message/index" &&
|
||||
const isViewingThisConversation =
|
||||
currentPage?.route === "pages/message/index" &&
|
||||
currentGroupID === conversation.groupID;
|
||||
|
||||
// 如果用户正在查看这个具体的会话,不增加未读数
|
||||
@ -533,6 +548,7 @@ onHide(() => {
|
||||
.avatar-container {
|
||||
position: relative;
|
||||
margin-right: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
|
||||
0
static/doctor-avatar.png
Normal file
BIN
static/home/archive-manage.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
static/home/arrow-right-blue.png
Normal file
|
After Width: | Height: | Size: 498 B |
BIN
static/home/arrow-right-gray.png
Normal file
|
After Width: | Height: | Size: 483 B |
81
static/home/basic-info-bg.svg
Normal file
@ -0,0 +1,81 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 155 72" class="design-iconfont">
|
||||
<g clip-path="url(#uzvb9kyd7__clip0_256_1041)">
|
||||
<rect width="155" height="72" rx="8" fill="url(#uzvb9kyd7__paint0_linear_256_1041)"/>
|
||||
<path transform="rotate(-45 -62 31.4264)" fill="url(#uzvb9kyd7__paint1_linear_256_1041)" fill-opacity=".06" d="M-62 31.4264H-2V111.4264H-62z"/>
|
||||
<path transform="rotate(-45 -50 3.42639)" fill="url(#uzvb9kyd7__paint2_linear_256_1041)" fill-opacity=".06" d="M-50 3.42639H10V83.42639H-50z"/>
|
||||
<g filter="url(#uzvb9kyd7__filter0_f_256_1041)">
|
||||
<path fill="#D0B783" fill-opacity=".1" d="M147 44A45 45 0 1 0 147 134A45 45 0 1 0 147 44Z"/>
|
||||
</g>
|
||||
<rect x="92" y="62" width="32" height="24" rx="6" transform="rotate(-30 92 62)" fill="url(#uzvb9kyd7__paint3_linear_256_1041)" fill-opacity=".7"/>
|
||||
<rect x="101" y="50.6808" width="40" height="32" rx="6" transform="rotate(-20 101 50.6808)" fill="url(#uzvb9kyd7__paint4_linear_256_1041)"/>
|
||||
<path d="M115 43C115 39.6863 117.686 37 121 37H149C152.314 37 155 39.6863 155 43V73H115V43Z" fill="url(#uzvb9kyd7__paint5_linear_256_1041)"/>
|
||||
<g filter="url(#uzvb9kyd7__filter1_d_256_1041)">
|
||||
<rect x="123" y="44" width="24" height="4" rx="2" fill="url(#uzvb9kyd7__paint6_linear_256_1041)" shape-rendering="crispEdges"/>
|
||||
</g>
|
||||
<g filter="url(#uzvb9kyd7__filter2_d_256_1041)">
|
||||
<path d="M136 52C137.105 52 138 52.8954 138 54V59H143C144.105 59 145 59.8954 145 61C145 62.1046 144.105 63 143 63H138V68C138 69.1046 137.105 70 136 70C134.895 70 134 69.1046 134 68V63H129C127.895 63 127 62.1046 127 61C127 59.8954 127.895 59 129 59H134V54C134 52.8954 134.895 52 136 52Z" fill="url(#uzvb9kyd7__paint7_linear_256_1041)" shape-rendering="crispEdges"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="uzvb9kyd7__paint0_linear_256_1041" x1="25.5294" y1="8" x2="82.8964" y2="66.7287" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F4F9FF"/>
|
||||
<stop offset="1" stop-color="#DBEAFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint1_linear_256_1041" x1="-61.3449" y1="67.5409" x2="-16.3935" y2="44.3755" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79B2F3" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#3063C7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint2_linear_256_1041" x1="-49.3449" y1="39.5409" x2="-4.39355" y2="16.3755" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79B2F3" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#3063C7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint3_linear_256_1041" x1="108" y1="62" x2="108" y2="86" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AAF5FA"/>
|
||||
<stop offset="1" stop-color="#3D9CCC" stop-opacity=".28"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint4_linear_256_1041" x1="115.841" y1="53.7618" x2="115.417" y2="87.4082" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4BCFB5"/>
|
||||
<stop offset="1" stop-color="#3987CC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint5_linear_256_1041" x1="115" y1="33.4" x2="168.238" y2="60.2917" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79B8F3"/>
|
||||
<stop offset="1" stop-color="#3063C7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint6_linear_256_1041" x1="123" y1="46" x2="147" y2="46" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#fff" stop-opacity=".7"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity=".6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="uzvb9kyd7__paint7_linear_256_1041" x1="125" y1="52" x2="137" y2="76" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#fff"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity=".3"/>
|
||||
</linearGradient>
|
||||
<filter id="uzvb9kyd7__filter0_f_256_1041" x="82" y="24" width="130" height="130" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="10" result="effect1_foregroundBlur_256_1041"/>
|
||||
</filter>
|
||||
<filter id="uzvb9kyd7__filter1_d_256_1041" x="119" y="42" width="32" height="12" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.103529 0 0 0 0 0.241569 0 0 0 0 0.517647 0 0 0 0.2 0"/>
|
||||
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_256_1041"/>
|
||||
<feBlend in="SourceGraphic" in2="effect1_dropShadow_256_1041" result="shape"/>
|
||||
</filter>
|
||||
<filter id="uzvb9kyd7__filter2_d_256_1041" x="123" y="50" width="26" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.103529 0 0 0 0 0.241569 0 0 0 0 0.517647 0 0 0 0.2 0"/>
|
||||
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_256_1041"/>
|
||||
<feBlend in="SourceGraphic" in2="effect1_dropShadow_256_1041" result="shape"/>
|
||||
</filter>
|
||||
<clipPath id="uzvb9kyd7__clip0_256_1041">
|
||||
<rect width="155" height="72" rx="8" fill="#fff"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
BIN
static/home/chat-consult.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
1
static/home/female.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1770103681929" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5978" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M877.714286 365.714286C877.714286 163.7504 713.963886 0 512 0S146.285714 163.7504 146.285714 365.714286c0 183.285029 134.999771 334.6432 310.857143 361.142857L457.142857 804.571429l-164.571429 0 0 109.714286 164.571429 0 0 109.714286 109.714286 0 0-109.714286 164.571429 0 0-109.714286-164.571429 0 0-77.714286C742.714514 700.357486 877.714286 548.999314 877.714286 365.714286zM256 365.714286c0-141.143771 114.856229-256 256-256s256 114.856229 256 256-114.856229 256-256 256S256 506.858057 256 365.714286z" fill="#F69661" p-id="5979"></path></svg>
|
||||
|
After Width: | Height: | Size: 880 B |
BIN
static/home/health-education.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
76
static/home/health-info-bg.svg
Normal file
@ -0,0 +1,76 @@
|
||||
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 155 72" class="design-iconfont">
|
||||
<g clip-path="url(#ntcrfa3do__clip0_256_3589)">
|
||||
<rect width="155" height="72" rx="8" fill="url(#ntcrfa3do__paint0_linear_256_3589)"/>
|
||||
<path transform="rotate(-45 -62 31.4264)" fill="url(#ntcrfa3do__paint1_linear_256_3589)" fill-opacity=".06" d="M-62 31.4264H-2V111.4264H-62z"/>
|
||||
<path transform="rotate(-45 -50 3.42639)" fill="url(#ntcrfa3do__paint2_linear_256_3589)" fill-opacity=".06" d="M-50 3.42639H10V83.42639H-50z"/>
|
||||
<g filter="url(#ntcrfa3do__filter0_f_256_3589)">
|
||||
<path fill="#D0B783" fill-opacity=".1" d="M147 44A45 45 0 1 0 147 134A45 45 0 1 0 147 44Z"/>
|
||||
</g>
|
||||
<g filter="url(#ntcrfa3do__filter1_f_256_3589)">
|
||||
<path fill="url(#ntcrfa3do__paint3_linear_256_3589)" fill-opacity=".1" d="M157 7A45 45 0 1 0 157 97A45 45 0 1 0 157 7Z"/>
|
||||
</g>
|
||||
<path d="M92 61C92 56.5817 95.5817 53 100 53H112V77H92V61Z" fill="url(#ntcrfa3do__paint4_linear_256_3589)" fill-opacity=".7"/>
|
||||
<path d="M112 47.6667C112 46.1939 113.194 45 114.667 45H155V74.3333C155 75.8061 153.806 77 152.333 77H114.667C113.194 77 112 75.8061 112 74.3333V47.6667Z" fill="url(#ntcrfa3do__paint5_linear_256_3589)"/>
|
||||
<path d="M135 35C139.418 35 143 38.5817 143 43V75H135V74C135 72.8954 134.105 72 133 72H131C129.895 72 129 72.8954 129 74V75H121V74C121 72.8954 120.105 72 119 72H117C115.895 72 115 72.8954 115 74V75H107V43C107 38.5817 110.582 35 115 35H135ZM117 59C115.895 59 115 59.8954 115 61V65C115 66.1046 115.895 67 117 67H119C120.105 67 121 66.1046 121 65V61C121 59.8954 120.105 59 119 59H117ZM131 59C129.895 59 129 59.8954 129 61V65C129 66.1046 129.895 67 131 67H133C134.105 67 135 66.1046 135 65V61C135 59.8954 134.105 59 133 59H131Z" fill="url(#ntcrfa3do__paint6_linear_256_3589)"/>
|
||||
<g filter="url(#ntcrfa3do__filter2_d_256_3589)">
|
||||
<path d="M125 41C126.105 41 127 41.8954 127 43V47H131C132.105 47 133 47.8954 133 49C133 50.1046 132.105 51 131 51H127V55C127 56.1046 126.105 57 125 57C123.895 57 123 56.1046 123 55V51H119C117.895 51 117 50.1046 117 49C117 47.8954 117.895 47 119 47H123V43C123 41.8954 123.895 41 125 41Z" fill="url(#ntcrfa3do__paint7_linear_256_3589)" shape-rendering="crispEdges"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="ntcrfa3do__paint0_linear_256_3589" x1="25.5294" y1="8" x2="82.8964" y2="66.7287" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#F4F9FF"/>
|
||||
<stop offset="1" stop-color="#DBEAFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint1_linear_256_3589" x1="-61.3449" y1="67.5409" x2="-16.3935" y2="44.3755" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79B2F3" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#3063C7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint2_linear_256_3589" x1="-49.3449" y1="39.5409" x2="-4.39355" y2="16.3755" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79B2F3" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#3063C7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint3_linear_256_3589" x1="157" y1="7" x2="157" y2="97" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#D0B783"/>
|
||||
<stop offset="1" stop-color="#EAD2A4"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint4_linear_256_3589" x1="102" y1="53" x2="102" y2="77" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#AAF5FA"/>
|
||||
<stop offset="1" stop-color="#3D9CCC" stop-opacity=".28"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint5_linear_256_3589" x1="134" y1="45" x2="155" y2="77" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#4BCFB5"/>
|
||||
<stop offset="1" stop-color="#3987CC"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint6_linear_256_3589" x1="107" y1="31" x2="158.516" y2="52.0775" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#79B8F3"/>
|
||||
<stop offset="1" stop-color="#3063C7"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ntcrfa3do__paint7_linear_256_3589" x1="115.222" y1="41" x2="125.889" y2="62.3333" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#fff"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity=".3"/>
|
||||
</linearGradient>
|
||||
<filter id="ntcrfa3do__filter0_f_256_3589" x="82" y="24" width="130" height="130" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="10" result="effect1_foregroundBlur_256_3589"/>
|
||||
</filter>
|
||||
<filter id="ntcrfa3do__filter1_f_256_3589" x="92" y="-13" width="130" height="130" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="10" result="effect1_foregroundBlur_256_3589"/>
|
||||
</filter>
|
||||
<filter id="ntcrfa3do__filter2_d_256_3589" x="113" y="39" width="24" height="24" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="2"/>
|
||||
<feGaussianBlur stdDeviation="2"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix values="0 0 0 0 0.103529 0 0 0 0 0.241569 0 0 0 0 0.517647 0 0 0 0.2 0"/>
|
||||
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow_256_3589"/>
|
||||
<feBlend in="SourceGraphic" in2="effect1_dropShadow_256_3589" result="shape"/>
|
||||
</filter>
|
||||
<clipPath id="ntcrfa3do__clip0_256_3589">
|
||||
<rect width="155" height="72" rx="8" fill="#fff"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
1
static/home/male.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1770103702423" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2069" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M914.285714 0 658.285714 0l0 109.714286 178.428343 0-160.393143 160.393143C605.429029 215.606857 516.928 182.857143 420.571429 182.857143 188.286171 182.857143 0 371.143314 0 603.428571s188.286171 420.571429 420.571429 420.571429 420.571429-188.286171 420.571429-420.571429c0-96.356571-32.749714-184.8576-87.250286-255.749486L914.285714 187.285943 914.285714 365.714286l109.714286 0L1024 109.714286 1024 0 914.285714 0zM420.571429 914.285714c-171.392 0-310.857143-139.465143-310.857143-310.857143s139.465143-310.857143 310.857143-310.857143 310.857143 139.465143 310.857143 310.857143S591.963429 914.285714 420.571429 914.285714z" fill="#1296db" p-id="2070"></path></svg>
|
||||
|
After Width: | Height: | Size: 1004 B |
BIN
static/home/my-education.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
static/home/my-questionnaire.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
static/home/service-rating.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
static/home/speaker-intro.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
static/home/switch-team.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
55
store/team.js
Normal file
@ -0,0 +1,55 @@
|
||||
import { computed, ref } from "vue";
|
||||
import { defineStore, storeToRefs } from "pinia";
|
||||
import api from '@/utils/api';
|
||||
import { toast } from '@/utils/widget';
|
||||
import useAccountStore from "./account";
|
||||
|
||||
|
||||
export default defineStore("teamStore", () => {
|
||||
const { account, doctorInfo } = storeToRefs(useAccountStore());
|
||||
const teams = ref([]);
|
||||
|
||||
const chargeTeams = computed(() => {
|
||||
const userid = doctorInfo.value?.userid;
|
||||
return teams.value.filter(team => {
|
||||
const memberLeaderList = Array.isArray(team.memberLeaderList) ? team.memberLeaderList : [];
|
||||
return memberLeaderList.includes(userid);
|
||||
});
|
||||
})
|
||||
|
||||
async function getTeam(teamId) {
|
||||
if (!teamId || !account.value?.corpId) return;
|
||||
const res = await api('getTeamData', { teamId, corpId: account.value.corpId });
|
||||
if (res && res.data) {
|
||||
return res.data;
|
||||
} else {
|
||||
toast(res?.message || '获取团队信息失败')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
async function getTeams() {
|
||||
const corpId = account.value?.corpId;
|
||||
const mateId = doctorInfo.value?.userid;
|
||||
if (!corpId || !mateId) return;
|
||||
const res = await api('getJoinedTeams', { corpId, mateId });
|
||||
teams.value = res && Array.isArray(res.data) ? res.data : [];
|
||||
}
|
||||
|
||||
// 获取团队成员头像和名称映射
|
||||
async function getTeamMemberAvatarsAndName(teamId) {
|
||||
if (!teamId || !account.value?.corpId) return {};
|
||||
const res = await api('getTeamMemberAvatarsAndName', {
|
||||
teamId,
|
||||
corpId: account.value.corpId
|
||||
});
|
||||
if (res && res.success && res.data) {
|
||||
return res.data;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
return { teams, chargeTeams, getTeam, getTeams, getTeamMemberAvatarsAndName }
|
||||
})
|
||||
@ -12,6 +12,7 @@ const urlsConfig = {
|
||||
getCorpMemberJob: "getCorpMemberJob",
|
||||
bindWxappWithTeam: 'bindWxappWithTeam',
|
||||
getWxappRelateTeams: 'getWxappRelateTeams',
|
||||
getTeamMemberAvatarsAndName: "getTeamMemberAvatarsAndName"
|
||||
},
|
||||
|
||||
knowledgeBase: {
|
||||
|
||||
@ -926,7 +926,7 @@ class TimChatManager {
|
||||
uni.removeStorageSync('account')
|
||||
uni.removeStorageSync('openid')
|
||||
uni.reLaunch({
|
||||
url: '/pages-center/login/login'
|
||||
url: '/pages/login/login'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@ -50,4 +50,89 @@ export async function confirm(content, opt = {}) {
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 保存图片到相册
|
||||
export async function saveImageToPhotosAlbum(filePath) {
|
||||
try {
|
||||
// 检查授权
|
||||
const authRes = await uni.getSetting()
|
||||
if (!authRes[1].authSetting['scope.writePhotosAlbum']) {
|
||||
// 请求授权
|
||||
try {
|
||||
await uni.authorize({ scope: 'scope.writePhotosAlbum' })
|
||||
} catch (err) {
|
||||
// 用户拒绝授权,引导去设置
|
||||
const [modalErr, modalRes] = await uni.showModal({
|
||||
title: '提示',
|
||||
content: '需要您授权保存相册',
|
||||
confirmText: '去设置',
|
||||
cancelText: '取消'
|
||||
})
|
||||
|
||||
if (modalRes && modalRes.confirm) {
|
||||
await uni.openSetting()
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 保存图片
|
||||
await uni.saveImageToPhotosAlbum({ filePath })
|
||||
await toast('保存成功')
|
||||
} catch (err) {
|
||||
console.error('保存图片失败:', err)
|
||||
await toast('保存失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 分享到微信
|
||||
export function shareToWeChat(options = {}) {
|
||||
const { title = '', path = '', imageUrl = '' } = options
|
||||
|
||||
return {
|
||||
title,
|
||||
path,
|
||||
imageUrl,
|
||||
success: () => {
|
||||
toast('分享成功')
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('分享失败:', err)
|
||||
toast('分享失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分享第三方小程序给微信好友
|
||||
export function shareThirdPartyMiniProgram(options = {}) {
|
||||
const {
|
||||
title = '',
|
||||
appId = '',
|
||||
path = '',
|
||||
imageUrl = '',
|
||||
webUrl = '',
|
||||
miniProgramType = 0
|
||||
} = options
|
||||
|
||||
if (!appId) {
|
||||
console.error('分享第三方小程序需要提供 appId')
|
||||
toast('分享配置错误')
|
||||
return null
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
path,
|
||||
imageUrl,
|
||||
miniProgramType, // 0-正式版 1-开发版 2-体验版
|
||||
webpageUrl: webUrl, // 兼容低版本的网页链接
|
||||
success: () => {
|
||||
toast('分享成功')
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('分享失败:', err)
|
||||
toast('分享失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||