22 <div class =" home" ref =" homeRef" >
33
44 <el-row :gutter =" 24" justify =" center" style =" margin-left : 0 ;margin-right : 0 ;" >
5+
56 <el-col :md =" 18" :sm =" 22" :xs =" 22" >
67 <ChatCard :qaId =" c['qaId']" :query =" c['query']" :answer =" c['answer']" :modelName =" c['modelName']"
78 :series =" c['series']" :responseTime =" c['responseTime']" :finishTime =" c['finishTime']"
1920 </div >
2021 </div >
2122 </el-col >
23+
24+ <canvas id =" live2d" ></canvas >
2225 </el-row >
2326 </div >
2427</template >
2528
2629<script >
30+ import loadLive2d from ' live2d-helper'
2731
2832export default {
2933 name: ' AppMain' ,
34+ data () {
35+ return {
36+ isLive2dLoading: false ,
37+ live2dError: null ,
38+ live2dInstance: null // 添加实例引用
39+ }
40+ },
3041 computed: {
3142 // 当前激活的聊天记录uuid
3243 active () {
@@ -40,55 +51,103 @@ export default {
4051 // 等app数据加载之后再执行逻辑 否则会闪屏
4152 is_show () {
4253 return this .$store .state .app .ready && this .active_session_qa_data .length === 0 ;
54+ },
55+ // 看板娘启用状态
56+ live2dEnabled () {
57+ return this .$store .state .setting .live2d_enabled || false ;
58+ },
59+ // 当前看板娘模型
60+ currentLive2dModel () {
61+ return this .$store .state .setting .live2d_model || null ;
4362 }
4463 },
45- watch: {
46- // 监听chat的变化,当变化时,表示在Bot回答,此时需要刷新滚动条的位置
47- " $store.state.app.chat" : {
48- deep: true , // 深度监听设置为 true
49- handler : function (newVal , oldVal ) {
50- // 检查是否滚动到底部 给200px的误差控制 这里的200px可以根据实际需求调整
51- let isAtBottom = this .$refs .homeRef .scrollTop + this .$refs .homeRef .clientHeight >= this .$refs .homeRef .scrollHeight - 200 ;
52- if (! isAtBottom) {
53- return ;
64+ methods: {
65+ // 统一处理滚动
66+ scrollToBottom () {
67+ this .$nextTick (() => {
68+ if (this .$refs .homeRef ) {
69+ this .$refs .homeRef .scrollTop = this .$refs .homeRef .scrollHeight ;
5470 }
55- // 内容更新时,保持滚动条的位置
56- this .$nextTick (() => {
57- this .$refs .homeRef .scrollTop = this .$refs .homeRef .scrollHeight
58- });
59- }
71+ });
6072 },
61- // 监听active的变化,当变化时,表示切换了聊天选项卡,此时需要把滚动条的位置设置到最下方
62- " $store.state.app.active" : {
63- deep: true , // 深度监听设置为 true
64- handler : function (newVal , oldVal ) {
65- // 内容更新时,保持滚动条的位置
66- this .$nextTick (() => {
67- this .$refs .homeRef .scrollTop = this .$refs .homeRef .scrollHeight
73+ // 初始化Live2D
74+ async initLive2d () {
75+ if (window .innerWidth <= 768 || ! this .live2dEnabled || ! this .currentLive2dModel ) {
76+ if (this .live2dInstance ) {
77+ // 清理现有实例
78+ this .live2dInstance .dispose && this .live2dInstance .dispose ();
79+ this .live2dInstance = null ;
80+ }
81+ return ;
82+ }
83+
84+ this .isLive2dLoading = true ;
85+ this .live2dError = null ;
86+
87+ try {
88+ // 清理现有实例
89+ if (this .live2dInstance ) {
90+ this .live2dInstance .dispose && this .live2dInstance .dispose ();
91+ }
92+
93+ this .live2dInstance = await loadLive2d ({
94+ canvas: " live2d" ,
95+ baseUrl: this .currentLive2dModel .substring (0 , this .currentLive2dModel .lastIndexOf (' /' )),
96+ model: this .currentLive2dModel ,
97+ globalFollowPointer: true ,
98+ allowSound: true ,
99+ height: " 800"
68100 });
101+ } catch (error) {
102+ console .error (' Live2D 加载失败:' , error);
103+ this .live2dError = error .message || ' 初始化失败' ;
104+ } finally {
105+ this .isLive2dLoading = false ;
69106 }
70107 },
71- query : function (newVal , oldVal ) {
72- // 内容更新时,保持滚动条的位置
73- this .$nextTick (() => {
74- this .$refs .homeRef .scrollTop = this .$refs .homeRef .scrollHeight
75- });
76- }
77- },
78- created () {
79- // 内容更新时,保持滚动条的位置
80- this .$nextTick (() => {
81- this .$refs .homeRef .scrollTop = this .$refs .homeRef .scrollHeight
82- });
83- },
84- methods: {
85108 /**
86109 * 跳转页面函数
87110 * @param path
88111 */
89112 goTo (path ) {
90113 this .$router .push (path)
91114 }
115+ },
116+ watch: {
117+ " $store.state.app.chat" : {
118+ deep: true ,
119+ handler : function (newVal , oldVal ) {
120+ const isAtBottom = this .$refs .homeRef .scrollTop + this .$refs .homeRef .clientHeight >= this .$refs .homeRef .scrollHeight - 200 ;
121+ if (isAtBottom) {
122+ this .scrollToBottom ();
123+ }
124+ }
125+ },
126+ " $store.state.app.active" : {
127+ deep: true ,
128+ handler : function () {
129+ this .scrollToBottom ();
130+ }
131+ },
132+ query () {
133+ this .scrollToBottom ();
134+ },
135+ currentLive2dModel: {
136+ handler : function () {
137+ this .initLive2d ();
138+ }
139+ },
140+ live2dEnabled: {
141+ handler : function () {
142+ this .initLive2d ();
143+ }
144+ }
145+ },
146+ mounted () {
147+ this .initLive2d ();
148+ },
149+ created () {
150+ this .scrollToBottom ();
92151 }
93152}
94153< / script>
@@ -151,4 +210,19 @@ export default {
151210.title - container .sub - title- line {
152211 font- size: 15px ;
153212}
213+
214+ /* 修改live2d容器样式 */
215+ #live2d {
216+ // border: 1px solid #000;
217+ width: 200px ;
218+ position: fixed; /* 改为固定定位 */
219+ bottom: 82px ; /* 固定在底部 */
220+ right: - 20px ; /* 固定在右侧 */
221+ z- index: 100 ; /* 确保在其他元素上层 */
222+
223+ /* 在小屏幕设备上隐藏live2d */
224+ @media screen and (max - width : 768px ) {
225+ display: none;
226+ }
227+ }
154228< / style>
0 commit comments