WYXD左右滑动翻页

This commit is contained in:
2026-07-28 17:48:57 +08:00
parent 85ecfc4c5b
commit c5958812cf
4 changed files with 98 additions and 66 deletions

View File

@@ -210,10 +210,6 @@
</view>
</view>
<!-- 底部锚点两个交替切换确保流式时每次都能触发滚动到底部 -->
<!-- <view>
<view id="chat-bottom-a" style="height: 0rpx;width: 1rpx;"></view>
<view id="chat-bottom-b" style="height: 0rpx;width: 1rpx;"></view>
</view> -->
<view id="chat-bottom-a" style="height: 1rpx;"></view>
<view id="chat-bottom-b" style="height: 1rpx;"></view>
</scroll-view>

View File

@@ -32,9 +32,14 @@
<!-- 幻灯片 -->
<view v-else class="wyxd-slide-area">
<scroll-view class="wyxd-slide-scroll" scroll-y :show-scrollbar="false">
<view class="wyxd-slide-card" v-html="currentSlide.html"></view>
</scroll-view>
<swiper class="wyxd-swiper" :current="currentIndex"
@change="onSwiperChange" :duration="250" easing-function="easeOutCubic">
<swiper-item v-for="(slide, idx) in slides" :key="idx">
<scroll-view class="wyxd-slide-scroll" scroll-y :show-scrollbar="false">
<view class="wyxd-slide-card" v-html="slide.html"></view>
</scroll-view>
</swiper-item>
</swiper>
</view>
</view>
@@ -89,10 +94,12 @@ const statusText = computed(() => {
const displayName = computed(() => fileName.value || '未命名文档')
const currentSlide = computed(() => slides.value[currentIndex.value] || { html: '' })
const pad = (n) => String(n).padStart(2, '0')
const onSwiperChange = (e) => {
currentIndex.value = e.detail.current
}
const goBack = () => {
uni.navigateBack()
}
@@ -247,6 +254,11 @@ onLoad((options) => {
/* padding: 20rpx; */
}
.wyxd-swiper {
width: 100%;
height: 100%;
}
.wyxd-slide-scroll {
height: 100%;
background: #fff;

View File

@@ -5639,7 +5639,7 @@ This will fail in production.`);
if (friendSocketStore.isConnected)
return;
if (!userToken.value || !UserId.value) {
formatAppLog("warn", "at pages/Chat/Chat.vue:349", "Token或UserId未准备好");
formatAppLog("warn", "at pages/Chat/Chat.vue:345", "Token或UserId未准备好");
return;
}
friendSocketStore.connect({
@@ -5725,7 +5725,7 @@ This will fail in production.`);
);
return html;
} catch (e2) {
formatAppLog("error", "at pages/Chat/Chat.vue:475", "解析失败", e2);
formatAppLog("error", "at pages/Chat/Chat.vue:471", "解析失败", e2);
return content;
}
};
@@ -5784,7 +5784,7 @@ This will fail in production.`);
files
};
} catch (e2) {
formatAppLog("error", "at pages/Chat/Chat.vue:552", "解析文件信息失败:", e2);
formatAppLog("error", "at pages/Chat/Chat.vue:548", "解析文件信息失败:", e2);
return {
textContent: content,
files: []
@@ -5822,7 +5822,7 @@ This will fail in production.`);
closeNewChatModal();
takeUserConversations();
} catch (error) {
formatAppLog("error", "at pages/Chat/Chat.vue:598", "新建普通会话失败:", error);
formatAppLog("error", "at pages/Chat/Chat.vue:594", "新建普通会话失败:", error);
uni.showToast({
title: "创建会话失败,请重试",
icon: "none"
@@ -5860,7 +5860,7 @@ This will fail in production.`);
};
const previewFileArray = vue.ref([]);
const uploadPhoto = () => {
formatAppLog("log", "at pages/Chat/Chat.vue:647", "点击了拍照上传");
formatAppLog("log", "at pages/Chat/Chat.vue:643", "点击了拍照上传");
uni.chooseImage({
count: 1,
sourceType: ["camera", "album"],
@@ -5883,7 +5883,7 @@ This will fail in production.`);
});
},
fail: (err) => {
formatAppLog("error", "at pages/Chat/Chat.vue:665", "选择图片失败", err);
formatAppLog("error", "at pages/Chat/Chat.vue:661", "选择图片失败", err);
}
});
};
@@ -5892,12 +5892,12 @@ This will fail in production.`);
};
const fileList = vue.ref([]);
const uploadFile = () => {
formatAppLog("log", "at pages/Chat/Chat.vue:676", "点击了上传文件");
formatAppLog("log", "at pages/Chat/Chat.vue:672", "点击了上传文件");
chooseFile({
count: 5,
type: "all",
success: (res) => {
formatAppLog("log", "at pages/Chat/Chat.vue:681", "成功了");
formatAppLog("log", "at pages/Chat/Chat.vue:677", "成功了");
fileList.value = res.tempFiles;
previewFileArray.value.push(...res.tempFiles);
uni.showToast({
@@ -5906,7 +5906,7 @@ This will fail in production.`);
});
},
fail: (err) => {
formatAppLog("error", "at pages/Chat/Chat.vue:692", "选择失败:", err);
formatAppLog("error", "at pages/Chat/Chat.vue:688", "选择失败:", err);
uni.showToast({
title: "选择失败",
icon: "error"
@@ -6108,7 +6108,7 @@ This will fail in production.`);
previewFileArray.value = [];
} catch (err) {
uni.hideLoading();
formatAppLog("error", "at pages/Chat/Chat.vue:927", "文件上传失败:", err);
formatAppLog("error", "at pages/Chat/Chat.vue:923", "文件上传失败:", err);
uni.showToast({
title: "文件上传失败,请重试",
icon: "error"
@@ -6242,15 +6242,15 @@ This will fail in production.`);
}
};
const stopConversation = async () => {
formatAppLog("log", "at pages/Chat/Chat.vue:1097", "中断对话 - 当前会话ID:", currentSessionId.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1093", "中断对话 - 当前会话ID:", currentSessionId.value);
try {
await socketStore.send({
type: "stop",
conversation_id: currentSessionId.value
});
formatAppLog("log", "at pages/Chat/Chat.vue:1103", "中断指令已发送成功");
formatAppLog("log", "at pages/Chat/Chat.vue:1099", "中断指令已发送成功");
} catch (err) {
formatAppLog("error", "at pages/Chat/Chat.vue:1105", "中断指令发送失败:", err);
formatAppLog("error", "at pages/Chat/Chat.vue:1101", "中断指令发送失败:", err);
}
if (streamingMessageId.value) {
allmessages.value = allmessages.value.filter((m) => m._id !== streamingMessageId.value);
@@ -6268,9 +6268,9 @@ This will fail in production.`);
});
};
vue.watch(() => socketStore.isThinking, (newVal, oldVal) => {
formatAppLog("log", "at pages/Chat/Chat.vue:1129", "isThinking 变化:", oldVal, "→", newVal, "messageString:", socketStore.messageString);
formatAppLog("log", "at pages/Chat/Chat.vue:1125", "isThinking 变化:", oldVal, "→", newVal, "messageString:", socketStore.messageString);
if (!oldVal && newVal) {
formatAppLog("log", "at pages/Chat/Chat.vue:1132", "AI开始回复跨设备同步锁定输入框");
formatAppLog("log", "at pages/Chat/Chat.vue:1128", "AI开始回复跨设备同步锁定输入框");
isThinking.value = true;
if (!streamingMessageId.value) {
streamingMessageId.value = "streaming-" + Date.now();
@@ -6284,7 +6284,7 @@ This will fail in production.`);
return;
}
if (oldVal && !newVal) {
formatAppLog("log", "at pages/Chat/Chat.vue:1148", "AI回复结束正常/中断),解锁并刷新消息列表");
formatAppLog("log", "at pages/Chat/Chat.vue:1144", "AI回复结束正常/中断),解锁并刷新消息列表");
if (streamingMessageId.value) {
allmessages.value = allmessages.value.filter((m) => m._id !== streamingMessageId.value);
streamingMessageId.value = null;
@@ -6336,15 +6336,15 @@ This will fail in production.`);
UserData.value = await getUserInfo(userToken.value);
UserId.value = UserData.value._id;
UserAvatar.value = UserData.value.avatar || "";
formatAppLog("log", "at pages/Chat/Chat.vue:1212", "用户信息已加载:", UserId.value, UserAvatar.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1208", "用户信息已加载:", UserId.value, UserAvatar.value);
} catch (error) {
formatAppLog("error", "at pages/Chat/Chat.vue:1214", "获取用户信息失败:", error);
formatAppLog("error", "at pages/Chat/Chat.vue:1210", "获取用户信息失败:", error);
}
};
const takeUserConversations = async () => {
try {
userToken.value = getToken();
formatAppLog("log", "at pages/Chat/Chat.vue:1222", "token:", userToken.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1218", "token:", userToken.value);
UserConversations.value = await getUserConversations(userToken.value) || [];
const savedSessionId = getCurrentSessionId();
if (savedSessionId && UserConversations.value.some((c) => c._id === savedSessionId)) {
@@ -6354,7 +6354,7 @@ This will fail in production.`);
} else {
currentSessionId.value = "";
}
formatAppLog("log", "at pages/Chat/Chat.vue:1234", "保存会话id", currentSessionId.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1230", "保存会话id", currentSessionId.value);
uni.setStorageSync("currentSessionId", currentSessionId.value);
} catch (error) {
uni.showToast({
@@ -6366,17 +6366,17 @@ This will fail in production.`);
const FriendInfoList = vue.ref([]);
const takeFriendList = async () => {
try {
formatAppLog("log", "at pages/Chat/Chat.vue:1249", "开始获取好友列表");
formatAppLog("log", "at pages/Chat/Chat.vue:1245", "开始获取好友列表");
const friendList = await getChatFriend(UserId.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1252", "friendList:", friendList);
formatAppLog("log", "at pages/Chat/Chat.vue:1248", "friendList:", friendList);
if (friendList && friendList.length) {
FriendInfoList.value = await takeUserAvatar(friendList);
} else {
FriendInfoList.value = [];
formatAppLog("log", "at pages/Chat/Chat.vue:1257", "好友列表为空");
formatAppLog("log", "at pages/Chat/Chat.vue:1253", "好友列表为空");
}
} catch (error) {
formatAppLog("error", "at pages/Chat/Chat.vue:1260", "获取好友列表失败:", error);
formatAppLog("error", "at pages/Chat/Chat.vue:1256", "获取好友列表失败:", error);
FriendInfoList.value = [];
} finally {
UserConversations.value = FriendInfoList.value;
@@ -6403,17 +6403,17 @@ This will fail in production.`);
};
});
} catch (err) {
formatAppLog("error", "at pages/Chat/Chat.vue:1290", "获取好友头像失败", err);
formatAppLog("error", "at pages/Chat/Chat.vue:1286", "获取好友头像失败", err);
return friendList;
}
};
const GroupList = vue.ref([]);
const takeGroupList = async () => {
try {
formatAppLog("log", "at pages/Chat/Chat.vue:1300", "开始获取群聊列表");
formatAppLog("log", "at pages/Chat/Chat.vue:1296", "开始获取群聊列表");
GroupList.value = await getGroup(UserId.value);
} catch (error) {
formatAppLog("error", "at pages/Chat/Chat.vue:1305", "获取群聊列表失败:", error);
formatAppLog("error", "at pages/Chat/Chat.vue:1301", "获取群聊列表失败:", error);
GroupList.value = [];
} finally {
UserConversations.value = GroupList.value;
@@ -6425,22 +6425,22 @@ This will fail in production.`);
return [];
try {
const memberIds = memberList.map((item) => item.groupContactId);
formatAppLog("log", "at pages/Chat/Chat.vue:1319", "请求头像的ID列表:", memberIds);
formatAppLog("log", "at pages/Chat/Chat.vue:1315", "请求头像的ID列表:", memberIds);
const memberAvatarList = await getUserAvatar(userToken.value, memberIds);
formatAppLog("log", "at pages/Chat/Chat.vue:1321", "头像接口返回数据:", memberAvatarList);
formatAppLog("log", "at pages/Chat/Chat.vue:1317", "头像接口返回数据:", memberAvatarList);
const userMap = new Map(memberAvatarList.map((user) => [user.user_id, user]) || []);
formatAppLog("log", "at pages/Chat/Chat.vue:1324", "userMap的keys:", Array.from(userMap.keys()));
formatAppLog("log", "at pages/Chat/Chat.vue:1320", "userMap的keys:", Array.from(userMap.keys()));
return memberList.map((member) => {
const memberId = member.groupContactId;
const userInfo = userMap.get(memberId);
formatAppLog("log", "at pages/Chat/Chat.vue:1329", `查找 ${memberId} 的头像:`, userInfo);
formatAppLog("log", "at pages/Chat/Chat.vue:1325", `查找 ${memberId} 的头像:`, userInfo);
return {
...member,
avatar: (userInfo == null ? void 0 : userInfo.avatar) || null
};
});
} catch (err) {
formatAppLog("error", "at pages/Chat/Chat.vue:1336", "获取群成员头像失败", err);
formatAppLog("error", "at pages/Chat/Chat.vue:1332", "获取群成员头像失败", err);
return memberList;
}
};
@@ -6487,12 +6487,12 @@ This will fail in production.`);
const takeGroupMessages = async () => {
try {
allmessages.value = await getGroupMessages(currentSessionId.value) || [];
formatAppLog("log", "at pages/Chat/Chat.vue:1400", "群聊消息:", allmessages.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1396", "群聊消息:", allmessages.value);
const memberList = await getGroupMemberList(currentSessionId.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1403", "获取到的群成员列表:", memberList);
formatAppLog("log", "at pages/Chat/Chat.vue:1399", "获取到的群成员列表:", memberList);
if (memberList && memberList.length) {
groupMemberList.value = await takeGroupMemberAvatar(memberList);
formatAppLog("log", "at pages/Chat/Chat.vue:1406", "群成员列表(带头像):", groupMemberList.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1402", "群成员列表(带头像):", groupMemberList.value);
} else {
groupMemberList.value = [];
}
@@ -6516,9 +6516,9 @@ This will fail in production.`);
}
};
vue.watch(() => friendSocketStore.MessageReceived, (newId) => {
formatAppLog("log", "at pages/Chat/Chat.vue:1453", "收到了好友消息");
formatAppLog("log", "at pages/Chat/Chat.vue:1449", "收到了好友消息");
if (newId) {
formatAppLog("log", "at pages/Chat/Chat.vue:1455", "ChatType:", ChatType.value);
formatAppLog("log", "at pages/Chat/Chat.vue:1451", "ChatType:", ChatType.value);
switch (ChatType.value) {
case 0:
takeConversationMessages();
@@ -6533,7 +6533,7 @@ This will fail in production.`);
friendSocketStore.MessageReceived = false;
break;
default:
formatAppLog("log", "at pages/Chat/Chat.vue:1471", "default 分支");
formatAppLog("log", "at pages/Chat/Chat.vue:1467", "default 分支");
friendSocketStore.MessageReceived = false;
break;
}
@@ -18033,8 +18033,10 @@ This will fail in production.`);
return map[status.value] || "处理中...";
});
const displayName = vue.computed(() => fileName.value || "未命名文档");
const currentSlide = vue.computed(() => slides.value[currentIndex.value] || { html: "" });
const pad = (n2) => String(n2).padStart(2, "0");
const onSwiperChange = (e2) => {
currentIndex.value = e2.detail.current;
};
const goBack = () => {
uni.navigateBack();
};
@@ -18070,18 +18072,18 @@ This will fail in production.`);
slides.value = [];
currentIndex.value = 0;
status.value = "downloading";
formatAppLog("log", "at pages/WYXD/WYXD.vue:134", "userToken.value", userToken.value);
formatAppLog("log", "at pages/WYXD/WYXD.vue:135", "workspaceId.value", workspaceId.value);
formatAppLog("log", "at pages/WYXD/WYXD.vue:136", "filePath.value", filePath.value);
formatAppLog("log", "at pages/WYXD/WYXD.vue:141", "userToken.value", userToken.value);
formatAppLog("log", "at pages/WYXD/WYXD.vue:142", "workspaceId.value", workspaceId.value);
formatAppLog("log", "at pages/WYXD/WYXD.vue:143", "filePath.value", filePath.value);
const tempPath = await downloadWyxdAsZip(
userToken.value,
workspaceId.value,
filePath.value
);
formatAppLog("log", "at pages/WYXD/WYXD.vue:140", "获取到的下载地址:", tempPath);
formatAppLog("log", "at pages/WYXD/WYXD.vue:147", "获取到的下载地址:", tempPath);
status.value = "extracting";
const extracted = await extractWyxd(tempPath);
formatAppLog("log", "at pages/WYXD/WYXD.vue:144", "extracted", extracted);
formatAppLog("log", "at pages/WYXD/WYXD.vue:151", "extracted", extracted);
status.value = "parsing";
const slideList = parseSlides(extracted.html, extracted.header, extracted.images);
if (!slideList || slideList.length === 0) {
@@ -18100,7 +18102,7 @@ This will fail in production.`);
status.value = "error";
const msg = typeof err === "string" ? err : err.message || "下载失败";
errorMsg.value = msg;
formatAppLog("error", "at pages/WYXD/WYXD.vue:167", "[WYXD] download error:", err);
formatAppLog("error", "at pages/WYXD/WYXD.vue:174", "[WYXD] download error:", err);
}
};
onLoad((options) => {
@@ -18108,8 +18110,8 @@ This will fail in production.`);
filePath.value = (options == null ? void 0 : options.filePath) ? decodeURIComponent(options.filePath) : "";
fileName.value = (options == null ? void 0 : options.fileName) ? decodeURIComponent(options.fileName) : "未命名文档";
userToken.value = (options == null ? void 0 : options.userToken) ?? uni.getStorageSync("user_token") ?? "";
formatAppLog("log", "at pages/WYXD/WYXD.vue:176", "页面接收options原始参数", options);
formatAppLog("log", "at pages/WYXD/WYXD.vue:177", "最终赋值变量:", {
formatAppLog("log", "at pages/WYXD/WYXD.vue:183", "页面接收options原始参数", options);
formatAppLog("log", "at pages/WYXD/WYXD.vue:184", "最终赋值变量:", {
workspaceId: workspaceId.value,
filePath: filePath.value,
fileName: fileName.value,
@@ -18121,7 +18123,7 @@ This will fail in production.`);
startDownload();
}
});
const __returned__ = { workspaceId, filePath, fileName, userToken, slides, currentIndex, status, loading, errorMsg, statusText, displayName, currentSlide, pad, goBack, prevSlide, nextSlide, loadFromCache, startDownload, ref: vue.ref, computed: vue.computed, get onLoad() {
const __returned__ = { workspaceId, filePath, fileName, userToken, slides, currentIndex, status, loading, errorMsg, statusText, displayName, pad, onSwiperChange, goBack, prevSlide, nextSlide, loadFromCache, startDownload, ref: vue.ref, computed: vue.computed, get onLoad() {
return onLoad;
}, get isWyxdCached() {
return isWyxdCached;
@@ -18201,16 +18203,34 @@ This will fail in production.`);
key: 2,
class: "wyxd-slide-area"
}, [
vue.createElementVNode("scroll-view", {
class: "wyxd-slide-scroll",
"scroll-y": "",
"show-scrollbar": false
vue.createElementVNode("swiper", {
class: "wyxd-swiper",
current: $setup.currentIndex,
onChange: $setup.onSwiperChange,
duration: 250,
"easing-function": "easeOutCubic"
}, [
vue.createElementVNode("view", {
class: "wyxd-slide-card",
innerHTML: $setup.currentSlide.html
}, null, 8, ["innerHTML"])
])
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList($setup.slides, (slide, idx) => {
return vue.openBlock(), vue.createElementBlock("swiper-item", { key: idx }, [
vue.createElementVNode("scroll-view", {
class: "wyxd-slide-scroll",
"scroll-y": "",
"show-scrollbar": false
}, [
vue.createElementVNode("view", {
class: "wyxd-slide-card",
innerHTML: slide.html
}, null, 8, ["innerHTML"])
])
]);
}),
128
/* KEYED_FRAGMENT */
))
], 40, ["current"])
]))
]),
$setup.slides.length > 1 ? (vue.openBlock(), vue.createElementBlock("view", {

View File

@@ -380,6 +380,10 @@
min-height: 0;
/* padding: 20rpx; */
}
.wyxd-swiper[data-v-507487c4] {
width: 100%;
height: 100%;
}
.wyxd-slide-scroll[data-v-507487c4] {
height: 100%;
background: #fff;