Commit 12faefcd654f1ab6a4bac448abff6e4fc49f98ed

Authored by chenxt
1 parent bc257923

ai语音弹窗

src/mobile/Ai/AiChatStyles.css
... ... @@ -78,7 +78,7 @@ body {
78 78 height: 120px;
79 79 position: fixed;
80 80 top: 39px;
81   - z-index: 999;
  81 + z-index: 200;
82 82 width: 100%;
83 83 }
84 84 .header-left h1 {
... ... @@ -97,7 +97,12 @@ body {
97 97 width: 40%;
98 98 flex-wrap: wrap;
99 99 }
100   -.model-selectors,
  100 +.model-Button {
  101 + position: fixed;
  102 + right: 10px;
  103 + top: 50px;
  104 + z-index: 200;
  105 +}
101 106 .model-selector {
102 107 background: rgba(255, 255, 255, 0.1);
103 108 border: 1px solid rgba(255, 255, 255, 0.2);
... ... @@ -128,7 +133,7 @@ body {
128 133 flex: 1;
129 134 overflow: hidden;
130 135 min-height: 0;
131   - margin-top: 160px;
  136 + margin-top: 100px;
132 137 }
133 138 .chat-main {
134 139 flex: 1;
... ... @@ -258,13 +263,17 @@ body {
258 263 bottom: 0;
259 264 left: 50%;
260 265 transform: translateX(-50%);
261   - z-index: 999;
  266 + z-index: 200;
262 267 width: 100%;
263 268 }
264 269 .input-wrapper {
265 270 display: flex;
266 271 gap: 10px;
267 272 position: relative;
  273 + align-items: center;
  274 +}
  275 +.input-icon {
  276 + font-size: 30px;
268 277 }
269 278 .message-input {
270 279 padding: 15px 20px;
... ... @@ -273,7 +282,7 @@ body {
273 282 font-size: 16px;
274 283 outline: none;
275 284 transition: border-color 0.3s;
276   - width: 60%;
  285 + width: 80%;
277 286 }
278 287 .message-input:focus {
279 288 border-color: #667eea;
... ... @@ -417,3 +426,40 @@ body {
417 426 height: 100%;
418 427 }
419 428 }
  429 +.phone-model {
  430 + position: fixed;
  431 + top: 0;
  432 + left: 0;
  433 + right: 0;
  434 + z-index: 201;
  435 + width: 100%;
  436 + height: 100%;
  437 +}
  438 +.phone-model .phone-zhezhao {
  439 + position: absolute;
  440 + top: 0;
  441 + left: 0;
  442 + right: 0;
  443 + z-index: 200;
  444 + width: 100%;
  445 + height: 100%;
  446 + background-color: #fff;
  447 +}
  448 +.phone-model .phone-phone {
  449 + position: absolute;
  450 + bottom: 40px;
  451 + left: 50%;
  452 + transform: translateX(-50%);
  453 + font-size: 50px;
  454 + z-index: 210;
  455 +}
  456 +.phone-model .phone-content {
  457 + position: absolute;
  458 + width: 90%;
  459 + height: 70%;
  460 + background-color: #f3f3f3;
  461 + z-index: 210;
  462 + left: 50%;
  463 + top: 10%;
  464 + transform: translateX(-50%);
  465 +}
... ...
src/mobile/Ai/AiChatStyles.less
... ... @@ -71,7 +71,7 @@ body {
71 71 height: 120px;
72 72 position: fixed;
73 73 top: 39px;
74   - z-index: 999;
  74 + z-index: 200;
75 75 width: 100%;
76 76 }
77 77  
... ... @@ -93,7 +93,12 @@ body {
93 93 width: 40%;
94 94 flex-wrap: wrap;
95 95 }
96   -.model-selectors,
  96 +.model-Button {
  97 + position: fixed;
  98 + right: 10px;
  99 + top: 50px;
  100 + z-index: 200;
  101 +}
97 102 .model-selector {
98 103 background: rgba(255,255,255,0.1);
99 104 border: 1px solid rgba(255,255,255,0.2);
... ... @@ -126,7 +131,7 @@ body {
126 131 flex: 1;
127 132 overflow: hidden;
128 133 min-height: 0;
129   - margin-top: 160px;
  134 + margin-top: 100px;
130 135 }
131 136  
132 137 .chat-main {
... ... @@ -277,7 +282,7 @@ body {
277 282 bottom: 0;
278 283 left: 50%;
279 284 transform: translateX(-50%);
280   - z-index: 999;
  285 + z-index: 200;
281 286 width: 100%;
282 287 }
283 288  
... ... @@ -285,8 +290,11 @@ body {
285 290 display: flex;
286 291 gap: 10px;
287 292 position: relative;
  293 + align-items: center;
  294 +}
  295 +.input-icon{
  296 + font-size: 30px;
288 297 }
289   -
290 298 .message-input {
291 299 padding: 15px 20px;
292 300 border: 2px solid #e9ecef;
... ... @@ -294,7 +302,7 @@ body {
294 302 font-size: 16px;
295 303 outline: none;
296 304 transition: border-color 0.3s;
297   - width: 60%;
  305 + width: 80%;
298 306 }
299 307  
300 308 .message-input:focus {
... ... @@ -441,4 +449,41 @@ body {
441 449 @keyframes wave {
442 450 0%, 100% { height: 20%; }
443 451 50% { height: 100%; }
  452 +}
  453 +.phone-model{
  454 + position: fixed;
  455 + top: 0;
  456 + left: 0;
  457 + right: 0;
  458 + z-index: 201;
  459 + width: 100%;
  460 + height: 100%;
  461 + .phone-zhezhao{
  462 + position: absolute;
  463 + top: 0;
  464 + left: 0;
  465 + right: 0;
  466 + z-index: 200;
  467 + width: 100%;
  468 + height: 100%;
  469 + background-color: #fff;
  470 + }
  471 + .phone-phone{
  472 + position: absolute;
  473 + bottom: 40px;
  474 + left: 50%;
  475 + transform: translateX(-50%);
  476 + font-size: 50px;
  477 + z-index: 210;
  478 + }
  479 + .phone-content{
  480 + position: absolute;
  481 + width: 90%;
  482 + height: 70%;
  483 + background-color: #f3f3f3;
  484 + z-index: 210;
  485 + left: 50%;
  486 + top: 10%;
  487 + transform: translateX(-50%);
  488 + }
444 489 }
445 490 \ No newline at end of file
... ...
src/mobile/Ai/newAi.jsx
1 1 import React, { useState, useEffect, useRef, useCallback } from 'react';
2 2 import ReactMarkdown from 'react-markdown';
3 3 import remarkGfm from 'remark-gfm';
4   -import { AudioOutline, AudioFill } from "antd-mobile-icons";
  4 +import { Button } from "antd-mobile";
  5 +import { LocationOutline, PhoneFill } from "antd-mobile-icons";
5 6 import './AiChatStyles.less';
6 7  
7 8 const ChatInterface = () => {
... ... @@ -17,6 +18,7 @@ const ChatInterface = () => {
17 18 const [welcomeContent, setWelcomeContent] = useState('');
18 19  
19 20 // 语音输入状态
  21 + const [isVoiceModel, setIsVoiceModel] = useState(false);
20 22 const [isRecording, setIsRecording] = useState(false);
21 23 const [isWsConnected, setIsWsConnected] = useState(false);
22 24 const [isVoiceMode, setIsVoiceMode] = useState(false);
... ... @@ -205,9 +207,6 @@ const ChatInterface = () => {
205 207 recordingTimerRef.current = setInterval(() => {
206 208 setRecordingDuration(prev => prev + 1);
207 209 }, 1000);
208   -
209   - console.log("录音已开始");
210   -
211 210 } catch (e) {
212 211 console.error("录音启动失败:", e);
213 212 alert("录音启动失败:" + e.message);
... ... @@ -407,17 +406,17 @@ const ChatInterface = () => {
407 406 } catch (error) {
408 407 console.error('请求失败:', error);
409 408 const errorMessage = `
410   -抱歉,请求出现错误:${error.message}
  409 + 抱歉,请求出现错误:${error.message}
411 410  
412   -**可能的原因:**
413   -1. Spring Boot 后端服务未启动
414   -2. API 接口路径不正确
415   -3. 网络连接问题
  411 + **可能的原因:**
  412 + 1. Spring Boot 后端服务未启动
  413 + 2. API 接口路径不正确
  414 + 3. 网络连接问题
416 415  
417   -**检查步骤:**
418   -1. 确保后端服务在端口 8099 运行
419   -2. 检查浏览器控制台查看详细错误
420   -3. 刷新页面重试
  416 + **检查步骤:**
  417 + 1. 确保后端服务在端口 8099 运行
  418 + 2. 检查浏览器控制台查看详细错误
  419 + 3. 刷新页面重试
421 420 `;
422 421 addMessage(errorMessage, 'ai', true);
423 422 } finally {
... ... @@ -466,33 +465,21 @@ const ChatInterface = () => {
466 465 const handleModelChange = (e) => {
467 466 setCurrentModel(e.target.value);
468 467 };
  468 + // 录音弹窗
  469 + const handlePhone = () => {
  470 + setIsVoiceModel(true)
  471 + startRecording();
  472 + }
469 473  
470 474 // ==================== 渲染 ====================
471 475 return (
472 476 <div className="ai-chat-container">
473   - {/* 头部 */}
474   - <div className="chat-header">
475   - <div className="header-left">
476   - <h1>小羚羊Ai-agent智能体</h1>
477   - <p>AI 印刷助手</p>
478   - </div>
479   - <div className="header-right">
480   - <select
481   - className="model-selector"
482   - value={currentModel}
483   - onChange={handleModelChange}
484   - >
485   - <option value="process">小羚羊印刷行业大模型</option>
486   - <option value="general">qwen2.5:14b</option>
487   - </select>
488   - <button
489   - className="model-selectors"
490   - onClick={handleClearChat}
491   - >
492   - 清空对话
493   - </button>
494   - </div>
495   - </div>
  477 + <Button
  478 + className="model-Button"
  479 + onClick={handleClearChat}
  480 + >
  481 + 清空对话
  482 + </Button>
496 483  
497 484 {/* 主体 */}
498 485 <div className="chat-body">
... ... @@ -570,7 +557,7 @@ const ChatInterface = () =&gt; {
570 557 {/* 输入区域 */}
571 558 <div className="input-section">
572 559 {/* 语音模式提示 - 仅在录音时显示 */}
573   - {isRecording && (
  560 + {/* {isRecording && (
574 561 <div className="voice-mode-indicator">
575 562 <div className="voice-wave">
576 563 <span></span>
... ... @@ -589,7 +576,7 @@ const ChatInterface = () =&gt; {
589 576 取消
590 577 </button>
591 578 </div>
592   - )}
  579 + )} */}
593 580  
594 581 <div className="input-wrapper">
595 582 <input
... ... @@ -612,37 +599,76 @@ const ChatInterface = () =&gt; {
612 599 disabled={isLoading}
613 600 readOnly={isRecording}
614 601 />
  602 + <PhoneFill className='input-icon' onClick={handlePhone} />
615 603  
  604 + <LocationOutline className='input-icon' onClick={handleSendMessage}
  605 + disabled={isLoading || isRecording} />
616 606 {/* 语音按钮 - 点击切换录音状态 */}
617   - <button
  607 + {/* <button
618 608 className={`voice-button ${isRecording ? 'recording' : ''}`}
619 609 onClick={toggleRecording}
620 610 disabled={isLoading}
621 611 >
622 612 {isRecording ? (
623 613 <>
624   - {/* <AudioFill className="voice-icon" /> */}
625 614 <span className="voice-text">结束录音</span>
626 615 </>
627 616 ) : (
628 617 <>
629   - {/* <AudioOutline className="voice-icon" /> */}
630 618 <span className="voice-text">点击录音</span>
631 619 </>
632 620 )}
633   - </button>
  621 + </button> */}
634 622  
635   - <button
  623 + {/* <button
636 624 className={`send-button ${isLoading ? 'disabled' : ''}`}
637 625 onClick={handleSendMessage}
638 626 disabled={isLoading || isRecording}
639 627 >
640 628 发送
641   - </button>
  629 + </button> */}
642 630 </div>
643 631 </div>
644 632 </div>
645 633 </div>
  634 + {
  635 + isVoiceModel ?
  636 + <div className='phone-model phone-zhezhao'>
  637 + <div className='phone-zhezhao'></div>
  638 + <div className='phone-content'>
  639 +
  640 + </div>
  641 + {/* 语音模式提示 - 仅在录音时显示 */}
  642 + {isRecording && (
  643 + <div className="voice-mode-indicator">
  644 + <div className="voice-wave">
  645 + <span></span>
  646 + <span></span>
  647 + <span></span>
  648 + <span></span>
  649 + <span></span>
  650 + </div>
  651 + <span className="voice-text">
  652 + 正在录音 {formatDuration(recordingDuration)}
  653 + </span>
  654 + <button
  655 + className="voice-cancel-btn"
  656 + onClick={cancelRecording}
  657 + >
  658 + 取消
  659 + </button>
  660 + </div>
  661 + )}
  662 + <div className='phone-phone' onClick={() => {
  663 + stopRecording()
  664 + setIsVoiceModel(false)
  665 + }}>
  666 + <PhoneFill color='red' />
  667 + </div>
  668 +
  669 + </div> : ''
  670 + }
  671 +
646 672 </div>
647 673 );
648 674 };
... ...
src/mobile/common/CommobileList.js
... ... @@ -136,7 +136,7 @@ class CommobileList extends React.Component {
136 136 {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
137 137 onClick={() => this.props.onCopyToClick(rowData)} */}
138 138 {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
139   - <li key={rowID} style={{ listStyle: 'none' }} onDoubleClick={() => this.handleDoubleClick(rowData)} >
  139 + <li key={rowID} style={{ listStyle: 'none' }} >
140 140 {
141 141 true ?
142 142 <div style={{ display: 'flex', justifyContent: 'space-between' }}>
... ...
src/routes/mobile/IndexMobile.js
... ... @@ -515,7 +515,7 @@ class IndexMobile extends React.Component {
515 515 commonBusiness.clearSocketData({ token, value: {}, sModelsId: 100 });
516 516 this.setState({
517 517 selectedTab: "ai",
518   - title: ai,
  518 + title: '小羚羊智能体',
519 519 });
520 520 history.push("/indexMobile/ai");
521 521 }}
... ...
src/utils/config.js
... ... @@ -9,7 +9,7 @@ const API = process.env.API;
9 9 const bHttps = false;
10 10 export const webSite = {
11 11 faceAddress: isDev ? '//km5cjx.gnway.cc:36867/xlyFace' : '//' + location.host + '/xlyFace',
12   - ipAddress: localStorage.ipAddress ? localStorage.ipAddress : isDev ? '//km5cjx.gnway.cc:37845/xlyEntry/' : '//' + location.host + '/xlyEntry/',
  12 + ipAddress: localStorage.ipAddress ? localStorage.ipAddress : isDev ? '//118.178.19.35:9198/xlyEntry_saas/' : '//' + location.host + '/xlyEntry/',
13 13  
14 14 // ipAddress: localStorage.ipAddress ? localStorage.ipAddress : isDev ? '//118.178.19.35:8088/xlyEntry/' : '//' + location.host + '/xlyEntry/',
15 15 // ipAddress: localStorage.ipAddress ? localStorage.ipAddress : isDev ? '//km5cjx.gnway.cc:36867/xlyEntry/' : '//' + location.host + '/xlyEntry/',
... ...