Browse Source

deepmate改成设计稿样式

wangyi/feature-20251022162725-启动页登录注册
Ethereal 4 weeks ago
parent
commit
3e640ea898
  1. 3
      package.json
  2. 357
      pages/deepMate/deepMate.vue

3
package.json

@ -1,7 +1,4 @@
{ {
"scripts": {
"server-deepchart": "json-server ./server/deepchart.json --port 8888"
},
"dependencies": { "dependencies": {
"json-server": "^1.0.0-beta.3", "json-server": "^1.0.0-beta.3",
"marked": "^2.0.1", "marked": "^2.0.1",

357
pages/deepMate/deepMate.vue

@ -3,20 +3,29 @@
<!-- 顶部导航栏 --> <!-- 顶部导航栏 -->
<view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> <view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
<view class="header-left"> <view class="header-left">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/f91e09b5987802185e7679055dafd272.svg" class="icon">
<image
src="https://d31zlh4on95l9h.cloudfront.net/images/f91e09b5987802185e7679055dafd272.svg"
class="icon"
>
</image> </image>
</view> </view>
<view class="header-center"
>
<text class="title"
:style="{ paddingTop: safeAreaInsets?.top + 'px' }"
>DeepMate</text>
<view class="header-center">
<text class="title" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"
>DeepMate</text
>
</view> </view>
<view class="header-right"> <view class="header-right">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/d7c4e74201213a25dd9574e908233928.svg" class="icon">
<image
src="https://d31zlh4on95l9h.cloudfront.net/images/d7c4e74201213a25dd9574e908233928.svg"
class="icon"
>
</image> </image>
<image style="margin-left: 10px;" src="https://d31zlh4on95l9h.cloudfront.net/images/099903c4aabf5713488b5cb60815e3f7.svg" class="icon"
@click="openHistoryDrawer"></image>
<image
style="margin-left: 10px"
src="https://d31zlh4on95l9h.cloudfront.net/images/099903c4aabf5713488b5cb60815e3f7.svg"
class="icon"
@click="openHistoryDrawer"
></image>
<!-- 新增新会话按钮 <!-- 新增新会话按钮
<button class="new-chat-button" @click="newChat"> <button class="new-chat-button" @click="newChat">
<text class="new-chat-text">新会话</text> <text class="new-chat-text">新会话</text>
@ -27,16 +36,22 @@
<!-- 主要内容区域 --> <!-- 主要内容区域 -->
<view class="main-content"> <view class="main-content">
<view class="banner-panel" v-if="messages.length === 0"> <view class="banner-panel" v-if="messages.length === 0">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/42e18bd7fe97d4f4f37aa70439a0990b.svg"
class="pray-banner"></image>
<image
src="https://d31zlh4on95l9h.cloudfront.net/images/42e18bd7fe97d4f4f37aa70439a0990b.svg"
class="pray-banner"
></image>
<view class="contain"> <view class="contain">
<!-- 机器人头像和欢迎语 --> <!-- 机器人头像和欢迎语 -->
<view class="robot-container" v-if="messages.length === 0"> <view class="robot-container" v-if="messages.length === 0">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg"
class="robot-avatar"></image>
<image
src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg"
class="robot-avatar"
></image>
<view class="welcome-message"> <view class="welcome-message">
<text class="greeting">Hi, 我是您的股市随身顾问~</text> <text class="greeting">Hi, 我是您的股市随身顾问~</text>
<text class="description">个股诊断市场情绪解读都可以找我</text>
<text class="description"
>个股诊断市场情绪解读都可以找我</text
>
</view> </view>
</view> </view>
@ -51,17 +66,22 @@
<view class="recommend-card" v-if="messages.length === 0"> <view class="recommend-card" v-if="messages.length === 0">
<view class="arrow" v-if="messages.length === 0"></view> <view class="arrow" v-if="messages.length === 0"></view>
<view class="card-content"> <view class="card-content">
<image src="../../static/images/tesla-logo.png" class="logo"></image>
<image
src="../../static/images/tesla-logo.png"
class="logo"
></image>
<view class="card-text"> <view class="card-text">
<text class="main-question">当前特斯拉该如何布局</text> <text class="main-question">当前特斯拉该如何布局</text>
<text class="stock-code">TSLA</text> <text class="stock-code">TSLA</text>
</view> </view>
<image src="https://d31zlh4on95l9h.cloudfront.net/images/40d94054644f6e3f1c366751f07f0010.svg"
class="arrow-icon" @click="goBlank"></image>
<image
src="https://d31zlh4on95l9h.cloudfront.net/images/40d94054644f6e3f1c366751f07f0010.svg"
class="arrow-icon"
@click="goBlank"
></image>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<!-- 可能感兴趣的话题 --> <!-- 可能感兴趣的话题 -->
<!-- <view v-if="messages.length === 0" class="interest-section"> <!-- <view v-if="messages.length === 0" class="interest-section">
@ -80,67 +100,86 @@
<!-- 顶部粘性欢迎块始终保留在聊天上方 --> <!-- 顶部粘性欢迎块始终保留在聊天上方 -->
<view class="chat-header" v-if="messages.length > 0"> <view class="chat-header" v-if="messages.length > 0">
<view class="robot-container"> <view class="robot-container">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg"
class="robot-avatar"></image>
<view class="welcome-message"> <text class="greeting">Hi, 我是您的股市随身顾问~</text> <text
class="description">个股诊断市场情绪解读都可以找我</text>
<image
src="https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg"
class="robot-avatar"
></image>
<view class="welcome-message">
<text class="greeting">Hi, 我是您的股市随身顾问~</text>
<text class="description"
>个股诊断市场情绪解读都可以找我</text
>
</view> </view>
</view> </view>
</view> </view>
<scroll-view class="chat-container" scroll-y="true" :scroll-top="chatScrollTop" @scroll="onChatScroll"
v-if="messages.length > 0">
<scroll-view
class="chat-container"
scroll-y="true"
:scroll-top="chatScrollTop"
@scroll="onChatScroll"
v-if="messages.length > 0"
>
<view class="message-list" id="messageList"> <view class="message-list" id="messageList">
<view v-for="(message, index) in messages" :key="index" :class="message.isUser ? 'message user-message' : 'message bot-message'
">
<view
v-for="(message, index) in messages"
:key="index"
:class="
message.isUser ? 'message user-message' : 'message bot-message'
"
>
<!-- 会话图标 --> <!-- 会话图标 -->
<text :class="message.isUser
<text
:class="
message.isUser
? 'fa-solid fa-user message-icon' ? 'fa-solid fa-user message-icon'
: 'fa-solid fa-robot message-icon' : 'fa-solid fa-robot message-icon'
"></text>
"
></text>
<!-- 会话内容 --> <!-- 会话内容 -->
<view class="message-content"> <view class="message-content">
<!-- <text class="message-text">{{ message.content }}</text> --> <!-- <text class="message-text">{{ message.content }}</text> -->
<!-- loading -->
<view
class="loading-dots"
v-if="message.isThinking || !message.isUser"
>
<view class="thinking-process">
<view class="thinking-header">
<view class="thinking-icon"></view>
<view class="thinking-title">{{
message.isTyping ? "正在思考" : "思考完成"
}}</view>
<view class="thinking-count">
</view>
<view
class="thinking-toggle"
@click="message.isThinking = !message.isThinking"
>
<span v-if="message.isThinking"></span>
<span v-else></span>
</view>
<!-- loading -->
<view
class="loading-dots"
v-if="message.isThinking || !message.isUser"
>
<view class="thinking-process">
<view class="thinking-header">
<view class="thinking-icon"></view>
<view class="thinking-title">{{
message.isTyping ? "正在思考" : "思考完成"
}}</view>
<view class="thinking-count"> </view>
<view
class="thinking-toggle"
@click="message.isThinking = !message.isThinking"
>
<span v-if="message.isThinking"></span>
<span v-else></span>
</view> </view>
<view v-show="message.isThinking" class="thinking-content">
<view class="thinking-item">
<view class="item-status">
<span class="checkmark"></span>
</view>
<view class="item-text">问题分析完成</view>
</view>
<view v-show="message.isThinking" class="thinking-content">
<view class="thinking-item">
<view class="item-status">
<span class="checkmark"></span>
</view> </view>
<view class="thinking-item">
<view class="item-status">
<span class="checkmark"></span>
</view>
<view class="item-text">收集相关信息</view>
<view class="item-text">问题分析完成</view>
</view>
<view class="thinking-item">
<view class="item-status">
<span class="checkmark"></span>
</view> </view>
<view class="item-text">收集相关信息</view>
</view> </view>
</view> </view>
</view> </view>
</view>
<!-- 使用 rich-text 渲染 Markdown 内容 --> <!-- 使用 rich-text 渲染 Markdown 内容 -->
<rich-text v-if="!message.isUser" class="message-text"
:nodes="renderMarkdown(message.content)"></rich-text>
<rich-text
v-if="!message.isUser"
class="message-text"
:nodes="renderMarkdown(message.content)"
></rich-text>
<text v-else class="message-text">{{ message.content }}</text> <text v-else class="message-text">{{ message.content }}</text>
</view> </view>
</view> </view>
@ -151,8 +190,14 @@
<!-- 输入框区域 --> <!-- 输入框区域 -->
<view class="input-area"> <view class="input-area">
<view class="input-wrapper"> <view class="input-wrapper">
<input type="text" placeholder="请输入股票代码/名称,获取AI洞察" placeholder-style="color:#fff;opacity:1" class="input-field"
v-model="inputMessage" @confirm="sendMessage" />
<input
type="text"
placeholder="请输入股票代码/名称,获取AI洞察"
placeholder-style="color:#fff;opacity:1"
class="input-field"
v-model="inputMessage"
@confirm="sendMessage"
/>
<image class="send-button" @click="sendMessage" :disabled="isSending"> <image class="send-button" @click="sendMessage" :disabled="isSending">
<!-- <image <!-- <image
src="https://d31zlh4on95l9h.cloudfront.net/images/95f1ea2262e9157db13c93c0dc1c5d96.svg" src="https://d31zlh4on95l9h.cloudfront.net/images/95f1ea2262e9157db13c93c0dc1c5d96.svg"
@ -160,17 +205,34 @@
></image> --> ></image> -->
</image> </image>
</view> </view>
<text class="disclaimer">以上数据由AI生成不作为最终投资建议决策需独立</text>
<text class="disclaimer"
>以上数据由AI生成不作为最终投资建议决策需独立</text
>
</view> </view>
<image class="back-to-top" src="https://d31zlh4on95l9h.cloudfront.net/images/ba357635d2bb480241952bb1cabacd73.svg"
:style="{ transform: 'translate3d(' + backTopX + 'px,' + backTopY + 'px,0)' }" @touchstart="onBackTopTouchStart"
@touchmove="onBackTopTouchMove" @touchend="onBackTopTouchEnd" @click="onBackTopClick"></image>
<image
class="back-to-top"
src="https://d31zlh4on95l9h.cloudfront.net/images/ba357635d2bb480241952bb1cabacd73.svg"
:style="{
transform: 'translate3d(' + backTopX + 'px,' + backTopY + 'px,0)',
}"
@touchstart="onBackTopTouchStart"
@touchmove="onBackTopTouchMove"
@touchend="onBackTopTouchEnd"
@click="onBackTopClick"
></image>
<!-- 搜索历史侧拉框 --> <!-- 搜索历史侧拉框 -->
<view class="drawer-overlay" v-show="showHistoryDrawer"></view> <view class="drawer-overlay" v-show="showHistoryDrawer"></view>
<view class="drawer-panel" v-show="showHistoryDrawer" @click.stop :style="{ transform: 'translateX(' + drawerOffsetX + 'px)' }">
<view class="drawer-back" @click="onDrawerBackClick"><text class="drawer-back-icon">></text></view>
<view
class="drawer-panel"
v-show="showHistoryDrawer"
@click.stop
:style="{ transform: 'translateX(' + drawerOffsetX + 'px)' }"
>
<view class="drawer-back" @click="onDrawerBackClick"
><text class="drawer-back-icon">></text></view
>
<view class="drawer-header"> <view class="drawer-header">
<text class="drawer-title">搜索历史</text> <text class="drawer-title">搜索历史</text>
<!-- <text class="drawer-close" @click="closeHistoryDrawer">×</text> --> <!-- <text class="drawer-close" @click="closeHistoryDrawer">×</text> -->
@ -179,7 +241,11 @@
<view v-if="searchHistory.length === 0" class="empty-history"> <view v-if="searchHistory.length === 0" class="empty-history">
<text>暂无搜索历史</text> <text>暂无搜索历史</text>
</view> </view>
<view v-for="(item, idx) in searchHistory" :key="idx" class="history-card">
<view
v-for="(item, idx) in searchHistory"
:key="idx"
class="history-card"
>
<text class="history-query">{{ item.query }}</text> <text class="history-query">{{ item.query }}</text>
<text class="history-time">{{ formatTime(item.time) }}</text> <text class="history-time">{{ formatTime(item.time) }}</text>
</view> </view>
@ -194,10 +260,10 @@
const { safeAreaInsets } = uni.getSystemInfoSync(); const { safeAreaInsets } = uni.getSystemInfoSync();
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from "vue"; import { ref, computed, onMounted, onUnmounted, watch, nextTick } from "vue";
import footerBar from '../../components/footerBar-cn'
import footerBar from "../../components/footerBar-cn";
import marked from "marked"; // marked import marked from "marked"; // marked
import { onPageScroll } from '@dcloudio/uni-app'
import {postStock,postIntent} from '../../api/deepMate/deepMate'
import { onPageScroll } from "@dcloudio/uni-app";
import { postStock, postIntent } from "../../api/deepMate/deepMate";
// marked // marked
marked.setOptions({ marked.setOptions({
renderer: new marked.Renderer(), renderer: new marked.Renderer(),
@ -253,7 +319,7 @@ const FAKE_MARKDOWN = `# <font color="#1890ff">Tesla Inc.全景作战报告</fon
--- ---
<font color="#8c8c8c">*该内容由AI生成仅供参考投资有风险请注意甄别*</font>`; <font color="#8c8c8c">*该内容由AI生成仅供参考投资有风险请注意甄别*</font>`;
const type = ref('member')
const type = ref("member");
const inputMessage = ref(""); const inputMessage = ref("");
const showThinking = ref(true); const showThinking = ref(true);
const isSending = ref(false); const isSending = ref(false);
@ -308,7 +374,10 @@ onMounted(() => {
// nextTick(startTabsMarquee); // nextTick(startTabsMarquee);
} }
if (messages.value.length > 0) { if (messages.value.length > 0) {
nextTick(() => { measureChatContainer(); scrollToBottom(); });
nextTick(() => {
measureChatContainer();
scrollToBottom();
});
} }
// //
@ -338,7 +407,7 @@ const generateUUID = () => {
// //
const measureChatContainer = () => { const measureChatContainer = () => {
const q = uni.createSelectorQuery(); const q = uni.createSelectorQuery();
q.select('.chat-container').boundingClientRect();
q.select(".chat-container").boundingClientRect();
q.exec((res) => { q.exec((res) => {
chatContainerHeight.value = res[0]?.height || 0; chatContainerHeight.value = res[0]?.height || 0;
}); });
@ -359,8 +428,12 @@ const goBlank = () => {
}; };
// //
const openHistoryDrawer = () => { showHistoryDrawer.value = true; };
const closeHistoryDrawer = () => { showHistoryDrawer.value = false; };
const openHistoryDrawer = () => {
showHistoryDrawer.value = true;
};
const closeHistoryDrawer = () => {
showHistoryDrawer.value = false;
};
const onDrawerBackClick = () => { const onDrawerBackClick = () => {
drawerOffsetX.value = 500; drawerOffsetX.value = 500;
setTimeout(() => { setTimeout(() => {
@ -370,7 +443,7 @@ const onDrawerBackClick = () => {
}; };
// YYYY-MM-DD HH:mm // YYYY-MM-DD HH:mm
const pad2 = (n) => (n < 10 ? '0' + n : '' + n);
const pad2 = (n) => (n < 10 ? "0" + n : "" + n);
const formatTime = (t) => { const formatTime = (t) => {
const d = new Date(t); const d = new Date(t);
const y = d.getFullYear(); const y = d.getFullYear();
@ -398,18 +471,20 @@ const sendMessage = () => {
// //
const entry = { query: userMessage.content, time: Date.now() }; const entry = { query: userMessage.content, time: Date.now() };
searchHistory.value.unshift(entry); searchHistory.value.unshift(entry);
uni.setStorageSync('search_history', searchHistory.value);
uni.setStorageSync("search_history", searchHistory.value);
// //
shouldAutoScroll.value = true; shouldAutoScroll.value = true;
nextTick(() => { scrollToBottom(); });
nextTick(() => {
scrollToBottom();
});
// //
simulateBotResponse(userMessage.content); simulateBotResponse(userMessage.content);
}; };
// //
const simulateBotResponse = async(userMessage) => {
const simulateBotResponse = async (userMessage) => {
isSending.value = true; isSending.value = true;
// //
@ -422,38 +497,38 @@ const simulateBotResponse = async(userMessage) => {
messages.value.push(botMsg); messages.value.push(botMsg);
await new Promise((resolve) => setTimeout(resolve, 2000));
await new Promise((resolve) => setTimeout(resolve, 2000));
// //
const res = await postIntent({ const res = await postIntent({
content:"森那美",
content: "森那美",
language: "cn", language: "cn",
marketlist: "hk,cn,usa,my,sg,vi,in,gb", marketlist: "hk,cn,usa,my,sg,vi,in,gb",
token: "9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnilrmTwo5FbqJ91WrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs",
token:
"9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnilrmTwo5FbqJ91WrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs",
model: "1", model: "1",
}); });
console.log("res"+res);
console.log("res" + res);
// //
if (res.code !== 200) { if (res.code !== 200) {
return ;
return;
} }
//
//
const recordId = res.data.recordId; const recordId = res.data.recordId;
const parentId = res.data.parentId; const parentId = res.data.parentId;
const stockId = res.data.stockId; const stockId = res.data.stockId;
await new Promise((resolve) => setTimeout(resolve, 2000));
await new Promise((resolve) => setTimeout(resolve, 2000));
// //
const StockInfo = await postStock({ const StockInfo = await postStock({
recordId, recordId,
parentId, parentId,
stockId, stockId,
token: "9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnilrmTwo5FbqJ91WrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs",
language:'cn'
token:
"9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnilrmTwo5FbqJ91WrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs",
language: "cn",
}); });
console.log("StockInfo", StockInfo); console.log("StockInfo", StockInfo);
@ -464,18 +539,13 @@ const simulateBotResponse = async(userMessage) => {
const markdown = StockInfo.markdown; const markdown = StockInfo.markdown;
console.log("StockInfo", StockInfo); console.log("StockInfo", StockInfo);
//
//
// const toDataInfo = await getData(); // const toDataInfo = await getData();
// console.log(toDataInfo); // console.log(toDataInfo);
// dataInfo.value = toDataInfo.data; // dataInfo.value = toDataInfo.data;
// console.log(dataInfo.value); // console.log(dataInfo.value);
messages.value[messages.value.length - 1].isThinking = false; messages.value[messages.value.length - 1].isThinking = false;
// //
nextTick(() => { nextTick(() => {
scrollToBottom(); scrollToBottom();
@ -486,39 +556,45 @@ const simulateBotResponse = async(userMessage) => {
let index = 0; let index = 0;
const botIndex = messages.value.length - 1; const botIndex = messages.value.length - 1;
const baseDelay = 165; //
const slowPunct = /[。!?!?;;]/; //
const midPunct = /[,、,::]/; //
const baseDelay = 5; //
const slowPunct = /[。!?!?;;]/; //
const midPunct = /[,、,::]/; //
const typeWriter = () => { const typeWriter = () => {
if (index < responseText.length) { if (index < responseText.length) {
const ch = responseText.charAt(index); const ch = responseText.charAt(index);
const current = messages.value[botIndex]; const current = messages.value[botIndex];
// //
messages.value.splice(
botIndex,
1,
{ ...current, content: current.content + ch, isTyping: true }
);
messages.value.splice(botIndex, 1, {
...current,
content: current.content + ch,
isTyping: true,
});
index++; index++;
scrollToBottom(); scrollToBottom();
const delay = slowPunct.test(ch) ? 220 : midPunct.test(ch) ? 120 : baseDelay;
const delay = slowPunct.test(ch)
? 220
: midPunct.test(ch)
? 120
: baseDelay;
setTimeout(typeWriter, delay); setTimeout(typeWriter, delay);
} else { } else {
const current = messages.value[botIndex]; const current = messages.value[botIndex];
messages.value.splice(
botIndex,
1,
{ ...current, isTyping: false }
);
messages.value.splice(botIndex, 1, { ...current, isTyping: false });
isSending.value = false; isSending.value = false;
nextTick(() => { scrollToBottom(); });
nextTick(() => {
scrollToBottom();
});
} }
}; };
// //
setTimeout(typeWriter, 500); setTimeout(typeWriter, 500);
console.log("messages", messages);
}; };
// //
@ -535,7 +611,7 @@ watch(messages, (arr) => {
const scrollToBottom = () => { const scrollToBottom = () => {
if (!shouldAutoScroll.value) return; if (!shouldAutoScroll.value) return;
const query = uni.createSelectorQuery(); const query = uni.createSelectorQuery();
query.select('#messageList').boundingClientRect();
query.select("#messageList").boundingClientRect();
query.exec((res) => { query.exec((res) => {
if (res[0]) { if (res[0]) {
latestContentHeight.value = res[0].height; latestContentHeight.value = res[0].height;
@ -563,7 +639,8 @@ const onChatScroll = (e) => {
return; return;
} }
const distanceToBottom = latestContentHeight.value - st - chatContainerHeight.value;
const distanceToBottom =
latestContentHeight.value - st - chatContainerHeight.value;
if (distanceToBottom <= AUTO_SCROLL_REENABLE_THRESHOLD) { if (distanceToBottom <= AUTO_SCROLL_REENABLE_THRESHOLD) {
shouldAutoScroll.value = true; shouldAutoScroll.value = true;
} }
@ -579,8 +656,14 @@ const backTopTargetY = ref(0);
let backTopRAF = 0; let backTopRAF = 0;
const backTopSmoothing = 0.15; // const backTopSmoothing = 0.15; //
const backTopEpsilon = 0.5; // const backTopEpsilon = 0.5; //
const raf = typeof requestAnimationFrame === 'function' ? requestAnimationFrame : (fn) => setTimeout(fn, 16);
const caf = typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame : (id) => clearTimeout(id);
const raf =
typeof requestAnimationFrame === "function"
? requestAnimationFrame
: (fn) => setTimeout(fn, 16);
const caf =
typeof cancelAnimationFrame === "function"
? cancelAnimationFrame
: (id) => clearTimeout(id);
function stepBackTop() { function stepBackTop() {
const dx = backTopTargetX.value - backTopX.value; const dx = backTopTargetX.value - backTopX.value;
@ -624,7 +707,10 @@ const onBackTopTouchMove = (e) => {
const ny = t.pageY - backTopDragOffset.value.y; const ny = t.pageY - backTopDragOffset.value.y;
const clampedX = clamp(nx, 0, sys.windowWidth - iconSize); const clampedX = clamp(nx, 0, sys.windowWidth - iconSize);
const clampedY = clamp(ny, 0, sys.windowHeight - reserveBottom - iconSize); const clampedY = clamp(ny, 0, sys.windowHeight - reserveBottom - iconSize);
if (Math.abs(clampedX - backTopX.value) + Math.abs(clampedY - backTopY.value) > 3) {
if (
Math.abs(clampedX - backTopX.value) + Math.abs(clampedY - backTopY.value) >
3
) {
backTopDragging.value = true; backTopDragging.value = true;
} }
backTopTargetX.value = clampedX; backTopTargetX.value = clampedX;
@ -640,8 +726,6 @@ const onBackTopClick = () => {
if (backTopDragging.value) return; // if (backTopDragging.value) return; //
scrollToTop(); scrollToTop();
}; };
</script> </script>
<style scoped> <style scoped>
@ -916,9 +1000,9 @@ const onBackTopClick = () => {
margin-bottom: 30rpx; margin-bottom: 30rpx;
} }
/* .user-message {
.user-message {
flex-direction: row-reverse; flex-direction: row-reverse;
} */
}
.message-icon { .message-icon {
font-size: 24rpx; font-size: 24rpx;
@ -934,8 +1018,8 @@ const onBackTopClick = () => {
} }
.user-message .message-icon { .user-message .message-icon {
background-color: transparent;
border-radius: 0;
background-color: #007aff;
border-radius: 40rpx;
/* padding: 0; /* padding: 0;
width: auto; width: auto;
height: auto; */ height: auto; */
@ -943,7 +1027,7 @@ const onBackTopClick = () => {
} }
.bot-message .message-icon { .bot-message .message-icon {
background: url('https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg');
background: url("https://d31zlh4on95l9h.cloudfront.net/images/61fa384381c88ad80be28f41827fe0e5.svg");
color: white; color: white;
} }
@ -1006,7 +1090,6 @@ const onBackTopClick = () => {
} }
@keyframes loading { @keyframes loading {
0%, 0%,
80%, 80%,
100% { 100% {
@ -1119,7 +1202,6 @@ const onBackTopClick = () => {
/* 在灰底之上、内容之下 */ /* 在灰底之上、内容之下 */
} }
.contain { .contain {
margin: 0 20rpx; margin: 0 20rpx;
gap: 5rpx; gap: 5rpx;
@ -1185,7 +1267,7 @@ const onBackTopClick = () => {
height: 28px; height: 28px;
border-radius: 14px; border-radius: 14px;
background: #fff; background: #fff;
box-shadow: 0 2px 8px rgba(0,0,0,.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
border: 1px solid #eee; border: 1px solid #eee;
display: flex; display: flex;
align-items: center; align-items: center;
@ -1233,9 +1315,18 @@ const onBackTopClick = () => {
.history-query { .history-query {
font-size: 28rpx; font-size: 28rpx;
color: #333333; color: #333333;
font-weight: 500; }
.history-time { margin-top: 8rpx; font-size: 22rpx; color: #888888; }
.empty-history { padding: 40rpx; color: #999999; text-align: center; }
font-weight: 500;
}
.history-time {
margin-top: 8rpx;
font-size: 22rpx;
color: #888888;
}
.empty-history {
padding: 40rpx;
color: #999999;
text-align: center;
}
.thinking-process { .thinking-process {
margin: 10rpx 0; margin: 10rpx 0;
border: 2rpx solid #e5e5e5; border: 2rpx solid #e5e5e5;

Loading…
Cancel
Save