fix: 提交
This commit is contained in:
parent
68e4f01bd2
commit
dcc84cf449
89
components/share-actions.vue
Normal file
89
components/share-actions.vue
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<view class="share-actions">
|
||||||
|
<view v-if="showSave" class="action-btn save-btn" @click="handleSave">
|
||||||
|
<text class="btn-text">{{ saveText }}</text>
|
||||||
|
</view>
|
||||||
|
<button
|
||||||
|
v-if="showShare"
|
||||||
|
class="action-btn share-btn"
|
||||||
|
open-type="share"
|
||||||
|
>
|
||||||
|
<text class="btn-text">{{ shareText }}</text>
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineProps, defineEmits } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
// 是否显示保存按钮
|
||||||
|
showSave: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 是否显示分享按钮
|
||||||
|
showShare: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 保存按钮文字
|
||||||
|
saveText: {
|
||||||
|
type: String,
|
||||||
|
default: '保存图片'
|
||||||
|
},
|
||||||
|
// 分享按钮文字
|
||||||
|
shareText: {
|
||||||
|
type: String,
|
||||||
|
default: '分享微信'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmits(['save', 'share'])
|
||||||
|
|
||||||
|
function handleSave() {
|
||||||
|
emit('save')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.share-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
padding: 0 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-btn {
|
||||||
|
border: 2rpx solid #0074ff;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-btn .btn-text {
|
||||||
|
color: #0074ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-btn {
|
||||||
|
background: #0074ff;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-btn::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-btn .btn-text {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,34 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="message-page">
|
<view class="message-page">
|
||||||
<!-- 头部组件 -->
|
<!-- 头部组件 -->
|
||||||
<message-header
|
<message-header v-model:activeTab="activeTab" @team-change="handleTeamChange" @add-patient="handleAddPatient" />
|
||||||
v-model:activeTab="activeTab"
|
|
||||||
@team-change="handleTeamChange"
|
|
||||||
@add-patient="handleAddPatient"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 消息列表 -->
|
<!-- 消息列表 -->
|
||||||
<scroll-view
|
<scroll-view class="message-list" scroll-y="true" refresher-enabled :refresher-triggered="refreshing"
|
||||||
class="message-list"
|
@refresherrefresh="handleRefresh" @scrolltolower="handleLoadMore">
|
||||||
scroll-y="true"
|
|
||||||
refresher-enabled
|
|
||||||
:refresher-triggered="refreshing"
|
|
||||||
@refresherrefresh="handleRefresh"
|
|
||||||
@scrolltolower="handleLoadMore"
|
|
||||||
>
|
|
||||||
<!-- 消息列表项 -->
|
<!-- 消息列表项 -->
|
||||||
<view
|
<view v-for="conversation in filteredConversationList"
|
||||||
v-for="conversation in filteredConversationList"
|
:key="conversation.groupID || conversation.conversationID" class="message-item"
|
||||||
:key="conversation.groupID || conversation.conversationID"
|
@click="handleClickConversation(conversation)">
|
||||||
class="message-item"
|
|
||||||
@click="handleClickConversation(conversation)"
|
|
||||||
>
|
|
||||||
<view class="avatar-container">
|
<view class="avatar-container">
|
||||||
<image
|
<image class="avatar" :src="conversation.avatar || '/static/default-avatar.png'"
|
||||||
class="avatar"
|
mode="aspectFill" />
|
||||||
:src="conversation.avatar || '/static/default-avatar.png'"
|
|
||||||
mode="aspectFill"
|
|
||||||
/>
|
|
||||||
<view v-if="conversation.unreadCount > 0" class="unread-badge">
|
<view v-if="conversation.unreadCount > 0" class="unread-badge">
|
||||||
<text class="unread-text">{{
|
<text class="unread-text">{{
|
||||||
conversation.unreadCount > 99 ? "99+" : conversation.unreadCount
|
conversation.unreadCount > 99 ? "99+" : conversation.unreadCount
|
||||||
@ -40,10 +24,7 @@
|
|||||||
<view class="header">
|
<view class="header">
|
||||||
<view class="name-info">
|
<view class="name-info">
|
||||||
<text class="name">{{ formatPatientName(conversation) }}</text>
|
<text class="name">{{ formatPatientName(conversation) }}</text>
|
||||||
<text
|
<text v-if="conversation.patientSex || conversation.patientAge" class="patient-info">
|
||||||
v-if="conversation.patientSex || conversation.patientAge"
|
|
||||||
class="patient-info"
|
|
||||||
>
|
|
||||||
{{ formatPatientInfo(conversation) }}
|
{{ formatPatientInfo(conversation) }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
@ -60,10 +41,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
<view
|
<view v-if="!loading && filteredConversationList.length === 0" class="empty-container">
|
||||||
v-if="!loading && filteredConversationList.length === 0"
|
|
||||||
class="empty-container"
|
|
||||||
>
|
|
||||||
<image class="empty-image" src="/static/empty.svg" mode="aspectFit" />
|
<image class="empty-image" src="/static/empty.svg" mode="aspectFit" />
|
||||||
<text class="empty-text">{{
|
<text class="empty-text">{{
|
||||||
activeTab === "processing" ? "暂无处理中的会话" : "暂无已结束的会话"
|
activeTab === "processing" ? "暂无处理中的会话" : "暂无已结束的会话"
|
||||||
@ -71,10 +49,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 加载更多 -->
|
<!-- 加载更多 -->
|
||||||
<view
|
<view v-if="hasMore && filteredConversationList.length > 0" class="load-more">
|
||||||
v-if="hasMore && filteredConversationList.length > 0"
|
|
||||||
class="load-more"
|
|
||||||
>
|
|
||||||
<text class="load-more-text">{{
|
<text class="load-more-text">{{
|
||||||
loadingMore ? "加载中..." : "上拉加载更多"
|
loadingMore ? "加载中..." : "上拉加载更多"
|
||||||
}}</text>
|
}}</text>
|
||||||
@ -84,40 +59,63 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from "vue";
|
import {
|
||||||
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
|
ref,
|
||||||
import { storeToRefs } from "pinia";
|
computed
|
||||||
import useAccountStore from "@/store/account.js";
|
} from "vue";
|
||||||
import useTeamStore from "@/store/team.js";
|
import {
|
||||||
import useInfoCheck from "@/hooks/useInfoCheck.js";
|
onLoad,
|
||||||
import { globalTimChatManager } from "@/utils/tim-chat.js";
|
onShow,
|
||||||
import { mergeConversationWithGroupDetails } from "@/utils/conversation-merger.js";
|
onHide
|
||||||
import MessageHeader from "./components/message-header.vue";
|
} from "@dcloudio/uni-app";
|
||||||
|
import {
|
||||||
|
storeToRefs
|
||||||
|
} from "pinia";
|
||||||
|
import useAccountStore from "@/store/account.js";
|
||||||
|
import useTeamStore from "@/store/team.js";
|
||||||
|
import useInfoCheck from "@/hooks/useInfoCheck.js";
|
||||||
|
import {
|
||||||
|
globalTimChatManager
|
||||||
|
} from "@/utils/tim-chat.js";
|
||||||
|
import {
|
||||||
|
mergeConversationWithGroupDetails
|
||||||
|
} from "@/utils/conversation-merger.js";
|
||||||
|
import MessageHeader from "./components/message-header.vue";
|
||||||
|
|
||||||
// 获取登录状态
|
// 获取登录状态
|
||||||
const { account, openid, isIMInitialized } = storeToRefs(useAccountStore());
|
const {
|
||||||
const { initIMAfterLogin } = useAccountStore();
|
account,
|
||||||
|
openid,
|
||||||
|
isIMInitialized
|
||||||
|
} = storeToRefs(useAccountStore());
|
||||||
|
const {
|
||||||
|
initIMAfterLogin
|
||||||
|
} = useAccountStore();
|
||||||
|
|
||||||
// 获取团队信息
|
// 获取团队信息
|
||||||
const teamStore = useTeamStore();
|
const teamStore = useTeamStore();
|
||||||
const { getTeams } = teamStore;
|
const {
|
||||||
|
getTeams
|
||||||
|
} = teamStore;
|
||||||
|
|
||||||
// 信息完善检查
|
// 信息完善检查
|
||||||
const { withInfo } = useInfoCheck();
|
const {
|
||||||
|
withInfo
|
||||||
|
} = useInfoCheck();
|
||||||
|
|
||||||
// 团队相关状态
|
// 团队相关状态
|
||||||
const currentTeamId = ref(""); // 空字符串表示"全部会话消息"
|
const currentTeamId = ref(""); // 空字符串表示"全部会话消息"
|
||||||
|
|
||||||
// 状态
|
// 状态
|
||||||
const conversationList = ref([]);
|
const conversationList = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const loadingMore = ref(false);
|
const loadingMore = ref(false);
|
||||||
const hasMore = ref(false);
|
const hasMore = ref(false);
|
||||||
const refreshing = ref(false);
|
const refreshing = ref(false);
|
||||||
const activeTab = ref("processing");
|
const activeTab = ref("processing");
|
||||||
|
|
||||||
// 根据 orderStatus 过滤会话列表
|
// 根据 orderStatus 过滤会话列表
|
||||||
const filteredConversationList = computed(() => {
|
const filteredConversationList = computed(() => {
|
||||||
let filtered = [];
|
let filtered = [];
|
||||||
|
|
||||||
if (activeTab.value === "processing") {
|
if (activeTab.value === "processing") {
|
||||||
@ -141,23 +139,23 @@ const filteredConversationList = computed(() => {
|
|||||||
filtered = filtered.filter((conv) => conv.teamId === currentTeamId.value);
|
filtered = filtered.filter((conv) => conv.teamId === currentTeamId.value);
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理团队切换
|
// 处理团队切换
|
||||||
const handleTeamChange = (teamId) => {
|
const handleTeamChange = (teamId) => {
|
||||||
currentTeamId.value = teamId;
|
currentTeamId.value = teamId;
|
||||||
console.log("切换到团队ID:", teamId);
|
console.log("切换到团队ID:", teamId);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 邀请患者 - 使用 withInfo 包装,确保信息完善后才能使用
|
// 邀请患者 - 使用 withInfo 包装,确保信息完善后才能使用
|
||||||
const handleAddPatient = withInfo(() => {
|
const handleAddPatient = withInfo(() => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "/pages/work/team/invite/invite-patient",
|
url: "/pages/work/team/invite/invite-patient",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// 初始化IM
|
// 初始化IM
|
||||||
const initIM = async () => {
|
const initIM = async () => {
|
||||||
if (!isIMInitialized.value) {
|
if (!isIMInitialized.value) {
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
title: "连接中...",
|
title: "连接中...",
|
||||||
@ -184,10 +182,10 @@ const initIM = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载会话列表
|
// 加载会话列表
|
||||||
const loadConversationList = async () => {
|
const loadConversationList = async () => {
|
||||||
if (loading.value) return;
|
if (loading.value) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
@ -232,13 +230,13 @@ const loadConversationList = async () => {
|
|||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 防抖更新定时器
|
// 防抖更新定时器
|
||||||
let updateTimer = null;
|
let updateTimer = null;
|
||||||
|
|
||||||
// 设置会话列表监听,实时更新列表
|
// 设置会话列表监听,实时更新列表
|
||||||
const setupConversationListener = () => {
|
const setupConversationListener = () => {
|
||||||
if (!globalTimChatManager) return;
|
if (!globalTimChatManager) return;
|
||||||
|
|
||||||
// 监听会话列表更新事件
|
// 监听会话列表更新事件
|
||||||
@ -309,7 +307,8 @@ const setupConversationListener = () => {
|
|||||||
const existing = conversationList.value[existingIndex];
|
const existing = conversationList.value[existingIndex];
|
||||||
if (
|
if (
|
||||||
existing.lastMessage !== conversationData.lastMessage ||
|
existing.lastMessage !== conversationData.lastMessage ||
|
||||||
existing.lastMessageTime !== conversationData.lastMessageTime ||
|
existing.lastMessageTime !== conversationData
|
||||||
|
.lastMessageTime ||
|
||||||
existing.unreadCount !== conversationData.unreadCount ||
|
existing.unreadCount !== conversationData.unreadCount ||
|
||||||
existing.patientName !== conversationData.patientName ||
|
existing.patientName !== conversationData.patientName ||
|
||||||
existing.patientSex !== conversationData.patientSex ||
|
existing.patientSex !== conversationData.patientSex ||
|
||||||
@ -387,15 +386,15 @@ const setupConversationListener = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 格式化患者姓名
|
// 格式化患者姓名
|
||||||
const formatPatientName = (conversation) => {
|
const formatPatientName = (conversation) => {
|
||||||
return conversation.patientName || "未知患者";
|
return conversation.patientName || "未知患者";
|
||||||
};
|
};
|
||||||
|
|
||||||
// 格式化患者信息(性别 + 年龄)
|
// 格式化患者信息(性别 + 年龄)
|
||||||
const formatPatientInfo = (conversation) => {
|
const formatPatientInfo = (conversation) => {
|
||||||
const parts = [];
|
const parts = [];
|
||||||
|
|
||||||
// 性别
|
// 性别
|
||||||
@ -411,10 +410,10 @@ const formatPatientInfo = (conversation) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return parts.join(" ");
|
return parts.join(" ");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 格式化消息时间
|
// 格式化消息时间
|
||||||
const formatMessageTime = (timestamp) => {
|
const formatMessageTime = (timestamp) => {
|
||||||
if (!timestamp) return "";
|
if (!timestamp) return "";
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
@ -453,10 +452,10 @@ const formatMessageTime = (timestamp) => {
|
|||||||
|
|
||||||
// 其他
|
// 其他
|
||||||
return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`;
|
return `${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点击会话
|
// 点击会话
|
||||||
const handleClickConversation = (conversation) => {
|
const handleClickConversation = (conversation) => {
|
||||||
console.log("点击会话:", conversation);
|
console.log("点击会话:", conversation);
|
||||||
|
|
||||||
// 立即清空本地未读数(优化用户体验)
|
// 立即清空本地未读数(优化用户体验)
|
||||||
@ -472,10 +471,10 @@ const handleClickConversation = (conversation) => {
|
|||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/message/index?conversationID=${conversation.conversationID}&groupID=${conversation.groupID}`,
|
url: `/pages/message/index?conversationID=${conversation.conversationID}&groupID=${conversation.groupID}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 加载更多
|
// 加载更多
|
||||||
const handleLoadMore = () => {
|
const handleLoadMore = () => {
|
||||||
if (loadingMore.value || !hasMore.value) return;
|
if (loadingMore.value || !hasMore.value) return;
|
||||||
|
|
||||||
loadingMore.value = true;
|
loadingMore.value = true;
|
||||||
@ -483,25 +482,25 @@ const handleLoadMore = () => {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
loadingMore.value = false;
|
loadingMore.value = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 下拉刷新
|
// 下拉刷新
|
||||||
const handleRefresh = async () => {
|
const handleRefresh = async () => {
|
||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
try {
|
try {
|
||||||
await loadConversationList();
|
await loadConversationList();
|
||||||
} finally {
|
} finally {
|
||||||
refreshing.value = false;
|
refreshing.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
console.log("消息列表页面加载");
|
console.log("消息列表页面加载");
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面显示
|
// 页面显示
|
||||||
onShow(async () => {
|
onShow(async () => {
|
||||||
try {
|
try {
|
||||||
// 加载团队列表
|
// 加载团队列表
|
||||||
await getTeams();
|
await getTeams();
|
||||||
@ -525,10 +524,10 @@ onShow(async () => {
|
|||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面隐藏
|
// 页面隐藏
|
||||||
onHide(() => {
|
onHide(() => {
|
||||||
// 清除防抖定时器
|
// 清除防抖定时器
|
||||||
if (updateTimer) {
|
if (updateTimer) {
|
||||||
clearTimeout(updateTimer);
|
clearTimeout(updateTimer);
|
||||||
@ -540,49 +539,49 @@ onHide(() => {
|
|||||||
globalTimChatManager.setCallback("onConversationListUpdated", null);
|
globalTimChatManager.setCallback("onConversationListUpdated", null);
|
||||||
globalTimChatManager.setCallback("onMessageReceived", null);
|
globalTimChatManager.setCallback("onMessageReceived", null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.message-page {
|
.message-page {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-list {
|
.message-list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-container,
|
.loading-container,
|
||||||
.empty-container {
|
.empty-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 100rpx 0;
|
padding: 100rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-text {
|
.loading-text {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-image {
|
.empty-image {
|
||||||
width: 200rpx;
|
width: 200rpx;
|
||||||
height: 200rpx;
|
height: 200rpx;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-text {
|
.empty-text {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-item {
|
.message-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 24rpx 32rpx;
|
padding: 24rpx 32rpx;
|
||||||
@ -592,21 +591,21 @@ onHide(() => {
|
|||||||
&:active {
|
&:active {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-container {
|
.avatar-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-right: 24rpx;
|
margin-right: 24rpx;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 96rpx;
|
width: 96rpx;
|
||||||
height: 96rpx;
|
height: 96rpx;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unread-badge {
|
.unread-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -8rpx;
|
top: -8rpx;
|
||||||
right: -8rpx;
|
right: -8rpx;
|
||||||
@ -618,37 +617,37 @@ onHide(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.unread-text {
|
.unread-text {
|
||||||
font-size: 20rpx;
|
font-size: 20rpx;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 8rpx;
|
margin-bottom: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name-info {
|
.name-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #333;
|
color: #333;
|
||||||
@ -656,42 +655,42 @@ onHide(() => {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.patient-info {
|
.patient-info {
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
padding-left: 12rpx;
|
padding-left: 12rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time {
|
.time {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
margin-left: 16rpx;
|
margin-left: 16rpx;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-preview {
|
.message-preview {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-text {
|
.preview-text {
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-more {
|
.load-more {
|
||||||
padding: 20rpx 0;
|
padding: 20rpx 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.load-more-text {
|
.load-more-text {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -42,8 +42,8 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="px-15 text-base text-gray leading-normal text-center">进入团队首页,即可发起线上咨询、建档授权等服务</view>
|
<view class="px-15 text-base text-gray leading-normal text-center">进入团队首页,即可发起线上咨询、建档授权等服务</view>
|
||||||
<view class="mt-10 flex px-15">
|
<view class="mt-10 flex px-15">
|
||||||
<view class="mr-10 border-auto rounded py-10 text-base text-primary text-center flex-grow">保存图片</view>
|
<view class="mr-10 border-auto rounded py-10 text-base text-primary text-center flex-grow" @click="saveImage">保存图片</view>
|
||||||
<view class="bg-primary rounded py-10 text-base text-white text-center flex-grow">分享微信</view>
|
<button class=" bg-primary rounded py-10 text-base text-white text-center flex-grow" open-type="share">分享微信</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -56,7 +56,7 @@ import { onLoad } from "@dcloudio/uni-app";
|
|||||||
import useAccountStore from "@/store/account.js";
|
import useAccountStore from "@/store/account.js";
|
||||||
import useGuard from '@/hooks/useGuard';
|
import useGuard from '@/hooks/useGuard';
|
||||||
import api from "@/utils/api.js";
|
import api from "@/utils/api.js";
|
||||||
import { toast } from "@/utils/widget";
|
import { toast, saveImageToPhotosAlbum, shareToWeChat } from "@/utils/widget";
|
||||||
|
|
||||||
import emptyData from "@/components/empty-data.vue";
|
import emptyData from "@/components/empty-data.vue";
|
||||||
import renamePopup from "./rename-popup.vue";
|
import renamePopup from "./rename-popup.vue";
|
||||||
@ -69,6 +69,7 @@ const current = ref(0);
|
|||||||
const list = ref([]);
|
const list = ref([]);
|
||||||
const visible = ref(false);
|
const visible = ref(false);
|
||||||
const teamId = ref('')
|
const teamId = ref('')
|
||||||
|
const qrcodes = ref(null);
|
||||||
const indicator = computed(() => ({
|
const indicator = computed(() => ({
|
||||||
prev: current.value > 0,
|
prev: current.value > 0,
|
||||||
next: current.value < list.value.length - 1
|
next: current.value < list.value.length - 1
|
||||||
@ -113,6 +114,65 @@ async function change(name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 保存二维码图片
|
||||||
|
async function saveImage() {
|
||||||
|
if (!team.value || !team.value.qrcode) {
|
||||||
|
toast('暂无二维码');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const qrcodeComponent = qrcodes.value[current.value];
|
||||||
|
if (!qrcodeComponent) {
|
||||||
|
toast('二维码未加载完成');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取二维码临时文件路径
|
||||||
|
const tempFilePath = qrcodeComponent.toTempFilePath();
|
||||||
|
if (tempFilePath) {
|
||||||
|
await saveImageToPhotosAlbum(tempFilePath);
|
||||||
|
} else {
|
||||||
|
toast('获取二维码失败');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('保存图片失败:', err);
|
||||||
|
toast('保存失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享配置
|
||||||
|
function onShareAppMessage() {
|
||||||
|
if (!team.value) {
|
||||||
|
return shareToWeChat({
|
||||||
|
title: '邀请患者加入团队',
|
||||||
|
path: '/pages/work/team/invite/invite-patient'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return shareToWeChat({
|
||||||
|
title: `邀请您加入${team.value.name}`,
|
||||||
|
path: `/pages/work/team/invite/invite-patient?teamId=${team.value.teamId}`,
|
||||||
|
imageUrl: team.value.qrcode || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享到朋友圈
|
||||||
|
function onShareTimeline() {
|
||||||
|
if (!team.value) {
|
||||||
|
return {
|
||||||
|
title: '邀请患者加入团队',
|
||||||
|
path: '/pages/work/team/invite/invite-patient'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
title: `邀请您加入${team.value.name}`,
|
||||||
|
query: `teamId=${team.value.teamId}`,
|
||||||
|
imageUrl: team.value.qrcode || ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
onLoad(opts => {
|
onLoad(opts => {
|
||||||
teamId.value = opts.teamId || '';
|
teamId.value = opts.teamId || '';
|
||||||
})
|
})
|
||||||
@ -121,6 +181,12 @@ useShow(() => {
|
|||||||
getTeams()
|
getTeams()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 导出分享方法供页面使用
|
||||||
|
defineExpose({
|
||||||
|
onShareAppMessage,
|
||||||
|
onShareTimeline
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.w-100 {
|
.w-100 {
|
||||||
@ -148,4 +214,15 @@ useShow(() => {
|
|||||||
.h-30 {
|
.h-30 {
|
||||||
height: 60rpx;
|
height: 60rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-btn {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
line-height: normal;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-btn::after {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
234
utils/share-usage-example.md
Normal file
234
utils/share-usage-example.md
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
# 微信小程序分享功能使用指南
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
提供了完整的微信小程序分享功能,包括:
|
||||||
|
- 分享给好友
|
||||||
|
- 分享到朋友圈
|
||||||
|
- 保存图片到相册
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
### 1. 基础分享(在页面中)
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<button open-type="share">分享给好友</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { createShareMessage, createShareTimeline } from '@/utils/share'
|
||||||
|
|
||||||
|
// 分享给好友
|
||||||
|
function onShareAppMessage() {
|
||||||
|
return createShareMessage({
|
||||||
|
title: '分享标题',
|
||||||
|
path: '/pages/index/index?id=123',
|
||||||
|
imageUrl: 'https://example.com/share.jpg'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享到朋友圈(需要在 app.json 中配置)
|
||||||
|
function onShareTimeline() {
|
||||||
|
return createShareTimeline({
|
||||||
|
title: '朋友圈标题',
|
||||||
|
query: 'id=123',
|
||||||
|
imageUrl: 'https://example.com/share.jpg'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出分享方法
|
||||||
|
defineExpose({
|
||||||
|
onShareAppMessage,
|
||||||
|
onShareTimeline
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 使用分享组件
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<share-actions
|
||||||
|
@save="handleSave"
|
||||||
|
:show-save="true"
|
||||||
|
:show-share="true"
|
||||||
|
save-text="保存图片"
|
||||||
|
share-text="分享微信"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { saveImageToAlbum, createShareMessage } from '@/utils/share'
|
||||||
|
import shareActions from '@/components/share-actions.vue'
|
||||||
|
|
||||||
|
// 保存图片
|
||||||
|
async function handleSave() {
|
||||||
|
const imagePath = 'https://example.com/image.jpg'
|
||||||
|
await saveImageToAlbum(imagePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享配置
|
||||||
|
function onShareAppMessage() {
|
||||||
|
return createShareMessage({
|
||||||
|
title: '分享标题',
|
||||||
|
path: '/pages/index/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
onShareAppMessage
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 保存二维码图片
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<uqrcode ref="qrcode" canvasId="qrcode" :value="qrcodeUrl" />
|
||||||
|
<button @click="saveQrcode">保存二维码</button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { saveImageToAlbum } from '@/utils/share'
|
||||||
|
import { toast } from '@/utils/widget'
|
||||||
|
|
||||||
|
const qrcode = ref(null)
|
||||||
|
const qrcodeUrl = ref('https://example.com')
|
||||||
|
|
||||||
|
async function saveQrcode() {
|
||||||
|
try {
|
||||||
|
if (!qrcode.value) {
|
||||||
|
toast('二维码未加载完成')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取二维码临时文件路径
|
||||||
|
const tempFilePath = qrcode.value.toTempFilePath()
|
||||||
|
if (tempFilePath) {
|
||||||
|
await saveImageToAlbum(tempFilePath)
|
||||||
|
} else {
|
||||||
|
toast('获取二维码失败')
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('保存失败:', err)
|
||||||
|
toast('保存失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 动态分享内容
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue'
|
||||||
|
import { createShareMessage } from '@/utils/share'
|
||||||
|
|
||||||
|
const currentItem = ref({
|
||||||
|
id: '123',
|
||||||
|
title: '商品标题',
|
||||||
|
image: 'https://example.com/product.jpg'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 动态生成分享配置
|
||||||
|
function onShareAppMessage() {
|
||||||
|
return createShareMessage({
|
||||||
|
title: currentItem.value.title,
|
||||||
|
path: `/pages/detail/detail?id=${currentItem.value.id}`,
|
||||||
|
imageUrl: currentItem.value.image
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
onShareAppMessage
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 配置说明
|
||||||
|
|
||||||
|
### 1. 启用分享到朋友圈
|
||||||
|
|
||||||
|
在 `pages.json` 中配置页面:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"path": "pages/index/index",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "首页",
|
||||||
|
"enableShareTimeline": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 全局分享配置
|
||||||
|
|
||||||
|
在 `App.vue` 中配置全局分享:
|
||||||
|
|
||||||
|
```vue
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
onShareAppMessage() {
|
||||||
|
return {
|
||||||
|
title: '默认分享标题',
|
||||||
|
path: '/pages/index/index'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShareTimeline() {
|
||||||
|
return {
|
||||||
|
title: '默认朋友圈标题'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API 说明
|
||||||
|
|
||||||
|
### createShareMessage(options)
|
||||||
|
|
||||||
|
创建分享给好友的配置
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `title` (string): 分享标题
|
||||||
|
- `path` (string): 分享路径
|
||||||
|
- `imageUrl` (string): 分享图片URL
|
||||||
|
|
||||||
|
**返回:** 分享配置对象
|
||||||
|
|
||||||
|
### createShareTimeline(options)
|
||||||
|
|
||||||
|
创建分享到朋友圈的配置
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `title` (string): 分享标题
|
||||||
|
- `query` (string): 分享路径参数
|
||||||
|
- `imageUrl` (string): 分享图片URL
|
||||||
|
|
||||||
|
**返回:** 分享配置对象
|
||||||
|
|
||||||
|
### saveImageToAlbum(filePath)
|
||||||
|
|
||||||
|
保存图片到相册
|
||||||
|
|
||||||
|
**参数:**
|
||||||
|
- `filePath` (string): 图片路径(本地临时路径或网络路径)
|
||||||
|
|
||||||
|
**返回:** Promise<boolean>
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 分享图片建议尺寸:5:4,推荐 500x400px
|
||||||
|
2. 分享路径必须是已注册的页面路径
|
||||||
|
3. 保存图片需要用户授权相册权限
|
||||||
|
4. 分享到朋友圈需要在页面配置中启用
|
||||||
|
5. 网络图片会自动下载后保存到相册
|
||||||
169
utils/share.js
Normal file
169
utils/share.js
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* 微信小程序分享工具
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { toast } from './widget'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建分享到好友的配置
|
||||||
|
* @param {Object} options 分享配置
|
||||||
|
* @param {string} options.title 分享标题
|
||||||
|
* @param {string} options.path 分享路径
|
||||||
|
* @param {string} options.imageUrl 分享图片URL
|
||||||
|
* @returns {Object} 分享配置对象
|
||||||
|
*/
|
||||||
|
export function createShareMessage(options = {}) {
|
||||||
|
const { title = '', path = '', imageUrl = '' } = options
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
path,
|
||||||
|
imageUrl,
|
||||||
|
success: () => {
|
||||||
|
toast('分享成功')
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('分享失败:', err)
|
||||||
|
toast('分享失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建分享到朋友圈的配置
|
||||||
|
* @param {Object} options 分享配置
|
||||||
|
* @param {string} options.title 分享标题
|
||||||
|
* @param {string} options.query 分享路径参数
|
||||||
|
* @param {string} options.imageUrl 分享图片URL
|
||||||
|
* @returns {Object} 分享配置对象
|
||||||
|
*/
|
||||||
|
export function createShareTimeline(options = {}) {
|
||||||
|
const { title = '', query = '', imageUrl = '' } = options
|
||||||
|
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
query,
|
||||||
|
imageUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在页面中启用分享功能
|
||||||
|
* 使用方法:在页面的 setup 中调用
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* import { enableShare } from '@/utils/share'
|
||||||
|
*
|
||||||
|
* // 在 setup 中
|
||||||
|
* enableShare({
|
||||||
|
* message: {
|
||||||
|
* title: '分享标题',
|
||||||
|
* path: '/pages/index/index',
|
||||||
|
* imageUrl: 'https://example.com/image.jpg'
|
||||||
|
* },
|
||||||
|
* timeline: {
|
||||||
|
* title: '朋友圈标题',
|
||||||
|
* query: 'id=123',
|
||||||
|
* imageUrl: 'https://example.com/image.jpg'
|
||||||
|
* }
|
||||||
|
* })
|
||||||
|
*/
|
||||||
|
export function enableShare(config = {}) {
|
||||||
|
const { message, timeline } = config
|
||||||
|
|
||||||
|
// 分享给好友
|
||||||
|
if (message) {
|
||||||
|
uni.$on('onShareAppMessage', () => {
|
||||||
|
return createShareMessage(message)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享到朋友圈
|
||||||
|
if (timeline) {
|
||||||
|
uni.$on('onShareTimeline', () => {
|
||||||
|
return createShareTimeline(timeline)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存图片到相册
|
||||||
|
* @param {string} filePath 图片路径(本地临时路径或网络路径)
|
||||||
|
*/
|
||||||
|
export async function saveImageToAlbum(filePath) {
|
||||||
|
try {
|
||||||
|
// 如果是网络图片,先下载
|
||||||
|
let localPath = filePath
|
||||||
|
if (filePath.startsWith('http')) {
|
||||||
|
const res = await uni.downloadFile({ url: filePath })
|
||||||
|
if (res[0]) {
|
||||||
|
throw new Error('下载图片失败')
|
||||||
|
}
|
||||||
|
localPath = res[1].tempFilePath
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查授权
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存图片
|
||||||
|
const [saveErr] = await uni.saveImageToPhotosAlbum({ filePath: localPath })
|
||||||
|
if (saveErr) {
|
||||||
|
throw saveErr
|
||||||
|
}
|
||||||
|
|
||||||
|
await toast('保存成功')
|
||||||
|
return true
|
||||||
|
} catch (err) {
|
||||||
|
console.error('保存图片失败:', err)
|
||||||
|
await toast('保存失败')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成带参数的小程序码
|
||||||
|
* 需要后端接口支持
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {string} options.scene 场景值
|
||||||
|
* @param {string} options.page 页面路径
|
||||||
|
* @returns {Promise<string>} 返回小程序码图片URL
|
||||||
|
*/
|
||||||
|
export async function generateMiniCode(options = {}) {
|
||||||
|
// 这里需要调用后端接口生成小程序码
|
||||||
|
// 示例代码,需要根据实际后端接口调整
|
||||||
|
try {
|
||||||
|
const res = await uni.request({
|
||||||
|
url: '/api/wechat/generateMiniCode',
|
||||||
|
method: 'POST',
|
||||||
|
data: options
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res[0] || !res[1].data.success) {
|
||||||
|
throw new Error('生成小程序码失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
return res[1].data.data.url
|
||||||
|
} catch (err) {
|
||||||
|
console.error('生成小程序码失败:', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -51,3 +51,46 @@ 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) {
|
||||||
|
await confirm('需要您授权保存相册', { title: '提示', showCancel: false })
|
||||||
|
await uni.openSetting()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存图片
|
||||||
|
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('分享失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user