冯杨

侧边栏做一些调整

@@ -8,17 +8,17 @@ def llm_response(message,nerfreal:BaseReal): @@ -8,17 +8,17 @@ def llm_response(message,nerfreal:BaseReal):
8 from openai import OpenAI 8 from openai import OpenAI
9 client = OpenAI( 9 client = OpenAI(
10 # 如果您没有配置环境变量,请在此处用您的API Key进行替换 10 # 如果您没有配置环境变量,请在此处用您的API Key进行替换
11 - # api_key=os.getenv("DASHSCOPE_API_KEY"),  
12 - api_key = "localkey",  
13 - base_url="http://127.0.0.1:5000/v1" 11 + api_key=os.getenv("DASHSCOPE_API_KEY"),
  12 + #api_key = "localkey",
  13 + #base_url="http://127.0.0.1:5000/v1"
14 # 填写DashScope SDK的base_url 14 # 填写DashScope SDK的base_url
15 - # base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", 15 + base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
16 ) 16 )
17 end = time.perf_counter() 17 end = time.perf_counter()
18 logger.info(f"llm Time init: {end-start}s") 18 logger.info(f"llm Time init: {end-start}s")
19 completion = client.chat.completions.create( 19 completion = client.chat.completions.create(
20 - model="fay-streaming",  
21 - # model="qwen-plus", 20 + # model="fay-streaming",
  21 + model="qwen-plus",
22 messages=[{'role': 'system', 'content': '你是小艺,是由艺云展陈开发的AI语音聊天机器人,回答风格精简。'}, 22 messages=[{'role': 'system', 'content': '你是小艺,是由艺云展陈开发的AI语音聊天机器人,回答风格精简。'},
23 {'role': 'user', 'content': message}], 23 {'role': 'user', 'content': message}],
24 stream=True, 24 stream=True,
@@ -13,7 +13,6 @@ @@ -13,7 +13,6 @@
13 font-family: Arial, sans-serif; 13 font-family: Arial, sans-serif;
14 display: flex; 14 display: flex;
15 height: 100vh; 15 height: 100vh;
16 - overflow: hidden;  
17 } 16 }
18 17
19 /* 侧边栏样式 */ 18 /* 侧边栏样式 */
@@ -49,32 +48,24 @@ @@ -49,32 +48,24 @@
49 #sidebar-toggle { 48 #sidebar-toggle {
50 position: fixed; 49 position: fixed;
51 top: 50%; 50 top: 50%;
52 - left: -24px;  
53 transform: translateY(-50%); 51 transform: translateY(-50%);
  52 + /* left is managed by JavaScript */
54 width: 48px; 53 width: 48px;
55 height: 48px; 54 height: 48px;
56 - background-color: #4285f4; 55 + background-color: #4285f4; /* Original color */
57 color: white; 56 color: white;
58 - border: none; 57 + border: none; /* Original border */
59 border-radius: 50%; 58 border-radius: 50%;
60 - display: flex; 59 + display: flex !important; /* Ensure it's displayed as flex */
61 align-items: center; 60 align-items: center;
62 justify-content: center; 61 justify-content: center;
63 cursor: pointer; 62 cursor: pointer;
64 - z-index: 100; 63 + z-index: 1002 !important; /* Higher than media's 1000, and ensure it applies */
65 font-size: 20px; 64 font-size: 20px;
66 box-shadow: 0 3px 8px rgba(0,0,0,0.2); 65 box-shadow: 0 3px 8px rgba(0,0,0,0.2);
67 - transition: all 0.3s ease;  
68 - }  
69 -  
70 - #sidebar-toggle {  
71 - left: 0;  
72 - }  
73 -  
74 - /* 收缩状态下的切换按钮位置调整 */  
75 - #sidebar.collapsed #sidebar-toggle {  
76 - left: 0;  
77 - background-color: #4285f4; 66 + transition: left 0.3s ease, background-color 0.3s ease, transform 0.3s ease;
  67 + opacity: 1 !important; /* Ensure opacity */
  68 + visibility: visible !important; /* Ensure visibility */
78 } 69 }
79 70
80 /* 主内容区域样式 */ 71 /* 主内容区域样式 */
@@ -177,7 +168,6 @@ @@ -177,7 +168,6 @@
177 visibility: visible !important; 168 visibility: visible !important;
178 opacity: 1 !important; 169 opacity: 1 !important;
179 } 170 }
180 -  
181 /* NEW: Fullscreen media when sidebar is collapsed */ 171 /* NEW: Fullscreen media when sidebar is collapsed */
182 #sidebar.collapsed ~ #main-content #media { 172 #sidebar.collapsed ~ #main-content #media {
183 position: fixed; 173 position: fixed;
@@ -235,9 +225,11 @@ @@ -235,9 +225,11 @@
235 </head> 225 </head>
236 <body> 226 <body>
237 227
  228 +<!-- 侧边栏切换按钮 (Moved to be a direct child of body) -->
  229 +<button id="sidebar-toggle"></button>
  230 +
238 <!-- 侧边栏 --> 231 <!-- 侧边栏 -->
239 <div id="sidebar"> 232 <div id="sidebar">
240 - <button id="sidebar-toggle"></button>  
241 <div> 233 <div>
242 <div class="section-title">连接控制</div> 234 <div class="section-title">连接控制</div>
243 <div class="option"> 235 <div class="option">
@@ -265,6 +257,20 @@ @@ -265,6 +257,20 @@
265 <button type="submit" class="btn btn-default">发送</button> 257 <button type="submit" class="btn btn-default">发送</button>
266 </form> 258 </form>
267 </div> 259 </div>
  260 +
  261 + <div>
  262 + <div class="section-title">服务器配置</div>
  263 + <div class="form-group">
  264 + <label for="ws-host">WebSocket 主机</label>
  265 + <input type="text" class="form-control" id="ws-host" placeholder="默认使用当前主机名">
  266 + </div>
  267 + <div class="form-group">
  268 + <label for="ws-port">WebSocket 端口</label>
  269 + <input type="text" class="form-control" id="ws-port" placeholder="默认: 10002">
  270 + </div>
  271 + <button id="save-ws-config" class="btn btn-default">保存配置</button>
  272 + <button id="reset-ws-config" class="btn btn-default">重置配置</button>
  273 + </div>
268 </div> 274 </div>
269 275
270 <!-- 主内容区域 --> 276 <!-- 主内容区域 -->
@@ -283,23 +289,138 @@ @@ -283,23 +289,138 @@
283 <script type="text/javascript" charset="utf-8"> 289 <script type="text/javascript" charset="utf-8">
284 290
285 $(document).ready(function() { 291 $(document).ready(function() {
  292 + var expandedSidebarLeft = '300px'; // Corresponds to #sidebar CSS width
  293 + var collapsedSidebarLeft = '10px'; // Test: offset from edge
  294 +
  295 + // Function to update toggle button based on sidebar state
  296 + function updateToggleButtonState() {
  297 + var sidebarIsCollapsed = $('#sidebar').hasClass('collapsed');
  298 + console.log('[Sidebar Toggle] Sidebar collapsed state:', sidebarIsCollapsed);
  299 + var toggleButton = $('#sidebar-toggle');
  300 + if (sidebarIsCollapsed) {
  301 + // Restore intended behavior: set left, icon, and original background color
  302 + // Relies on base CSS for top: 50% and transform: translateY(-50%)
  303 + toggleButton.html('≫').css({
  304 + 'left': collapsedSidebarLeft, // This is '10px'
  305 + 'background-color': '#4285f4', // Original color
  306 + 'top': '50%', // Ensure it matches base CSS
  307 + 'transform': 'translateY(-50%)' // Ensure it matches base CSS
  308 + });
  309 + console.log('[Sidebar Toggle] Action: Set to collapsed state. Left:', collapsedSidebarLeft, 'HTML:', toggleButton.html());
  310 + } else {
  311 + // Restore intended behavior: set left, icon, and original background color
  312 + toggleButton.html('≪').css({
  313 + 'left': expandedSidebarLeft,
  314 + 'background-color': '#4285f4', // Original color
  315 + 'top': '50%', // Ensure it matches base CSS
  316 + 'transform': 'translateY(-50%)' // Ensure it matches base CSS
  317 + });
  318 + console.log('[Sidebar Toggle] Action: Set to expanded state. Left:', expandedSidebarLeft, 'HTML:', toggleButton.html());
  319 + }
  320 + // Log applied styles to be sure
  321 + console.log('[Sidebar Toggle] Applied style attribute:', toggleButton.attr('style'));
  322 + console.log('[Sidebar Toggle] Computed z-index:', toggleButton.css('z-index'));
  323 + console.log('[Sidebar Toggle] Computed opacity:', toggleButton.css('opacity'));
  324 + console.log('[Sidebar Toggle] Computed visibility:', toggleButton.css('visibility'));
  325 + console.log('[Sidebar Toggle] Computed display:', toggleButton.css('display'));
  326 + console.log('[Sidebar Toggle] Offset:', toggleButton.offset());
  327 + console.log('[Sidebar Toggle] Position:', toggleButton.position());
  328 + }
  329 +
  330 + // Initial state setup for the toggle button
  331 + updateToggleButtonState();
  332 +
  333 + // Load saved WebSocket configuration or set defaults
  334 + function loadWsConfig() {
  335 + var savedWsHost = localStorage.getItem('wsHost');
  336 + var savedWsPort = localStorage.getItem('wsPort');
  337 +
  338 + if (savedWsHost) {
  339 + $('#ws-host').val(savedWsHost);
  340 + } else {
  341 + $('#ws-host').val('127.0.0.1'); // Default host
  342 + }
  343 +
  344 + if (savedWsPort) {
  345 + $('#ws-port').val(savedWsPort);
  346 + } else {
  347 + $('#ws-port').val('10002'); // Default port
  348 + }
  349 + }
  350 + loadWsConfig(); // Load config on document ready
  351 +
286 // 侧边栏切换功能 352 // 侧边栏切换功能
287 $('#sidebar-toggle').click(function() { 353 $('#sidebar-toggle').click(function() {
288 $('#sidebar').toggleClass('collapsed'); 354 $('#sidebar').toggleClass('collapsed');
289 -  
290 - // 切换按钮图标  
291 - if ($('#sidebar').hasClass('collapsed')) {  
292 - $(this).html('≫');  
293 - } else {  
294 - $(this).html('≪');  
295 - } 355 + updateToggleButtonState();
296 }); 356 });
297 357
298 - // 展开侧边栏按钮功能  
299 - $('#expand-sidebar').click(function() {  
300 - $('#sidebar').removeClass('collapsed');  
301 - $('#sidebar-toggle').html('≪'); 358 + // Note: The original '#expand-sidebar'.click handler was part of the replaced block.
  359 + // If an element with id #expand-sidebar exists and needs to control the sidebar,
  360 + // its click handler should be re-implemented similar to this:
  361 + // $('#expand-sidebar').click(function() {
  362 + // if ($('#sidebar').hasClass('collapsed')) {
  363 + // $('#sidebar').removeClass('collapsed');
  364 + // updateToggleButtonState();
  365 + // }
  366 + // });
  367 +
  368 + // Server configuration save and reset
  369 + $('#save-ws-config').click(function() {
  370 + var wsHost = $('#ws-host').val().trim();
  371 + var wsPort = $('#ws-port').val().trim();
  372 +
  373 + if (!wsHost) {
  374 + alert('WebSocket 主机不能为空。');
  375 + $('#ws-host').focus();
  376 + return;
  377 + }
  378 + if (!wsPort) {
  379 + alert('WebSocket 端口不能为空。');
  380 + $('#ws-port').focus();
  381 + return;
  382 + }
  383 +
  384 + localStorage.setItem('wsHost', wsHost);
  385 + localStorage.setItem('wsPort', wsPort);
  386 +
  387 + var originalText = $(this).text();
  388 + $(this).text('已保存!').prop('disabled', true);
  389 + setTimeout(function() {
  390 + $('#save-ws-config').text(originalText).prop('disabled', false);
  391 + }, 1500);
  392 +
  393 + console.log('WebSocket configuration saved: Host - ' + wsHost + ', Port - ' + wsPort);
  394 + // alert('配置已保存!更改将在下次连接时生效或您可以手动重新连接。');
  395 + });
  396 +
  397 + $('#reset-ws-config').click(function() {
  398 + $('#ws-host').val('127.0.0.1');
  399 + $('#ws-port').val('10002');
  400 + // No need to explicitly remove, connectWebSocket will use defaults if inputs are changed to defaults
  401 + // localStorage.removeItem('wsHost');
  402 + // localStorage.removeItem('wsPort');
  403 +
  404 + var originalText = $(this).text();
  405 + $(this).text('已重置!').prop('disabled', true);
  406 +
  407 + // Also update save button to reflect that new defaults need saving
  408 + var saveButton = $('#save-ws-config');
  409 + var saveButtonOriginalText = saveButton.text();
  410 + if (saveButton.text() !== '已保存!') { // Only change if not in 'saved' state
  411 + saveButton.text('保存默认值');
  412 + }
  413 +
  414 + setTimeout(function() {
  415 + $('#reset-ws-config').text(originalText).prop('disabled', false);
  416 + if (saveButton.text() === '保存默认值') {
  417 + saveButton.text(saveButtonOriginalText);
  418 + }
  419 + }, 1500);
  420 + console.log('WebSocket configuration reset to default values in fields.');
  421 + // alert('配置已重置为默认值,请点击“保存配置”以应用。');
302 }); 422 });
  423 +
303 // Old WebSocket code commented out 424 // Old WebSocket code commented out
304 // var host = window.location.hostname 425 // var host = window.location.hostname
305 // var ws = new WebSocket("ws://"+host+":8000/humanecho"); 426 // var ws = new WebSocket("ws://"+host+":8000/humanecho");
@@ -412,7 +533,13 @@ @@ -412,7 +533,13 @@
412 setUsername(); 533 setUsername();
413 function connectWebSocket() { 534 function connectWebSocket() {
414 var host = window.location.hostname; 535 var host = window.location.hostname;
415 - ws = new WebSocket("ws://127.0.0.1:10002"); 536 + // 获取WebSocket服务器地址,优先使用配置值,否则使用当前主机名
  537 + var wsHost = localStorage.getItem('wsHost') || host;
  538 + var wsPort = localStorage.getItem('wsPort') || '10002';
  539 + var wsProtocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
  540 + var wsUrl = wsProtocol + wsHost + ':' + wsPort;
  541 + console.log('Connecting to WebSocket server:', wsUrl);
  542 + ws = new WebSocket(wsUrl);
416 ws.onopen = function() { 543 ws.onopen = function() {
417 console.log('Connected to WebSocket on port 10002'); 544 console.log('Connected to WebSocket on port 10002');
418 reconnectAttempts = 0; // 重置重连次数 545 reconnectAttempts = 0; // 重置重连次数