xiaoguang_li 1 месяц назад
Родитель
Сommit
b4bb7de76a
1 измененных файлов с 199 добавлено и 1 удалено
  1. 199 1
      desktop/core/src/desktop/templates/assist.mako

+ 199 - 1
desktop/core/src/desktop/templates/assist.mako

@@ -2710,6 +2710,189 @@ from desktop.views import _ko
     })();
   </script>
 
+  <script type="text/html" id="chat-panel-template">
+    <div class="assist-inner-panel">
+      <div class="assist-flex-panel">
+        <style>
+            .display-area {
+              overflow-y: auto;
+              background-color: #fff;
+              padding: 10px;
+              display: flex;
+              flex-direction: column;
+            }
+            .message {
+              padding: 10px 14px;
+              margin-bottom: 8px;
+              max-width: 95%;
+              word-wrap: break-word;
+              line-height: 1.5;
+              border-radius: 18px;
+              padding-bottom: 3px;
+            }
+
+            /* AI 消息:靠左,蓝色背景 */
+            .ai-message {
+              align-self: flex-start;
+              background-color: #e3f2fd;
+              color: #0a0a0a;
+            }
+
+            /* 用户消息:靠右,绿色背景 */
+            .user-message {
+              align-self: flex-end;
+              background-color: #c8e6c9;
+              color: #0a0a0a;
+            }
+
+            .input-area {
+              display: flex;
+              padding: 10px;
+              background-color: #f9f9f9;
+              border-top: 1px solid #eee;
+            }
+
+            .user-input {
+              flex: 1;
+              padding: 10px 10px 10px 15px;
+              border: 1px solid #ccc;
+              border-radius: 4px;
+              outline: none;
+              resize: none;
+              overflow-y: auto;
+              scrollbar-gutter: stable;
+              min-height: auto;
+              max-height: 100px;
+              line-height: 1.5;
+              font-size: 16px;
+            }
+
+            .send-btn {
+              margin-left: 10px;
+              padding: 1px 15px;
+              background-color: #007bff;
+              color: white;
+              border: none;
+              border-radius: 4px;
+              cursor: pointer;
+            }
+
+            .send-btn:hover {
+              background-color: #0056b3;
+            }
+
+        </style>
+        <div class="assist-flex-header">
+          <div class="assist-inner-header">
+            <div class="function-dialect-dropdown" data-bind="component: { name: 'hue-drop-down', params: { fixedPosition: true, value: activeType, entries: availableTypes, linkTitle: '${ _ko('Selected dialect') }' } }" style="display: inline-block"></div>
+          </div>
+        </div>
+        <!-- 显示区域 -->
+        <div class="display-area" data-bind="foreach: messages">
+            <!-- 消息 -->
+            <div class="message" data-bind="html: content, css:{ 'ai-message': type==='ai', user-message: type==='user'}"></div>
+        </div>
+
+        <!-- 输入区域 -->
+        <div class="input-area">
+            <textarea class="user-input clearable" placeholder="请输入你的问题..."
+                      data-bind="clearable: query, textInput: query, event: { keydown: ask, input: autoResize} "></textarea>
+            <button class="send-btn" data-bind="click: answer">发送</button>
+        </div>
+      </div>
+    </div>
+  </script>
+
+  <script type="text/javascript">
+    (function () {
+
+      function ChatPanel(params) {
+        let self = this;
+        self.disposals = [];
+
+        self.activeType = ko.observable();
+        self.availableTypes = ko.observableArray(window.IS_EMBEDDED ? ['Impala'] : ['Hive', 'Impala', 'Pig']);
+        self.query = ko.observable().extend({ rateLimit: 400 });
+        self.messages = ko.observableArray([]);
+
+        self.availableTypes().forEach(function (type) {
+          self.initFunctions(type);
+        });
+
+        let apiHelper = ApiHelper.getInstance();
+
+        self.activeType.subscribe(function (newType) {
+          apiHelper.setInTotalStorage('assist', 'chat.panel.active.type', newType);
+        });
+
+        let lastActiveType = apiHelper.getFromTotalStorage('assist', 'chat.panel.active.type', self.availableTypes()[0]);
+        self.activeType(lastActiveType);
+
+        let updateType = function (type) {
+          self.availableTypes().every(function (availableType) {
+            if (availableType.toLowerCase() === type) {
+              if (self.activeType() !== availableType) {
+                self.activeType(availableType);
+              }
+              return false;
+            }
+            return true;
+          });
+        };
+
+        var activeSnippetTypeSub = huePubSub.subscribe('active.snippet.type.changed', updateType);
+
+        self.disposals.push(function () {
+          activeSnippetTypeSub.remove();
+        });
+
+        huePubSub.subscribeOnce('set.active.snippet.type', updateType);
+        huePubSub.publish('get.active.snippet.type');
+
+        var autoResize = function (data, event) {
+          var inputArea = event.target;
+          inputArea.style.height = 'auto';
+          inputArea.style.height = inputArea.scrollHeight + 'px';
+        };
+
+        autoResize();
+      }
+
+      ChatPanel.prototype.dispose = function () {
+        let self = this;
+        self.disposals.forEach(function (dispose) {
+          dispose();
+        })
+      };
+
+      ChatPanel.prototype.ask = function (data, event) {
+        let self = this;
+        if (event.key === 'Enter' || event.keyCode === 13) {
+          self.answer();
+        }
+      };
+
+      ChatPanel.prototype.answer = function () {
+        let self = this;
+        if (self.query.trim() === '') {
+            return
+        }
+        self.messages.push({type:'user', content: self.query().trim()});
+        self.messages.push({type:'ai', content: '感谢提问!我已经收到你的消息:' + self.query().trim()});
+      };
+
+      ChatPanel.prototype.initFunctions = function (dialect) {
+        var self = this;
+
+      };
+
+      ko.components.register('chat-panel', {
+        viewModel: ChatPanel,
+        template: { element: 'chat-panel-template' }
+      });
+    })();
+  </script>
+
   <script type="text/html" id="editor-assistant-panel-template">
     <div class="assist-inner-panel assist-assistant-panel">
       <div class="assist-flex-panel">
@@ -3615,7 +3798,7 @@ from desktop.views import _ko
       <div class="right-assist-tab" data-bind="visible: editorAssistantTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Assistant') }" data-bind="css: { 'blue' : activeTab() === 'editorAssistant' }, tooltip: { placement: 'left' }, click: editorAssistantTabClick"><i class="fa fa-fw fa-compass"></i></a></div>
       <div class="right-assist-tab" data-bind="visible: dashboardAssistantTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Assistant') }" data-bind="css: { 'blue' : activeTab() === 'dashboardAssistant' }, tooltip: { placement: 'left' }, click: dashboardAssistantTabClick"><i class="fa fa-fw fa-compass"></i></a></div>
       <div class="right-assist-tab" data-bind="visible: functionsTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Functions') }" data-bind="css: { 'blue' : activeTab() === 'functions' }, tooltip: { placement: 'left' }, click: functionsTabClick"><i class="fa fa-fw fa-superscript"></i></a></div>
-      <div class="right-assist-tab" data-bind="visible: functionsTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Functions') }" data-bind="css: { 'blue' : activeTab() === 'functions' }, tooltip: { placement: 'left' }, click: functionsTabClick"><i class="fa fa-fw fa-comments"></i></a></div>
+      <div class="right-assist-tab" data-bind="visible: chatTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Functions') }" data-bind="css: { 'blue' : activeTab() === 'chat' }, tooltip: { placement: 'left' }, click: chatTabClick"><i class="fa fa-fw fa-comments"></i></a></div>
       <div class="right-assist-tab" data-bind="visible: langRefTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Language Reference') }" data-bind="css: { 'blue' : activeTab() === 'langRef' }, tooltip: { placement: 'left' }, click: langRefTabClick"><i class="fa fa-fw fa-book"></i></a></div>
       <div class="right-assist-tab" data-bind="visible: schedulesTabAvailable" style="display:none;"><a class="inactive-action" href="javascript: void(0);" title="${ _('Schedule') }" data-bind="css: { 'blue' : activeTab() === 'schedules' }, tooltip: { placement: 'left' }, click: schedulesTabClick"><i class="fa fa-fw fa-calendar"></i></a></div>
     </div>
@@ -3630,6 +3813,10 @@ from desktop.views import _ko
       <div data-bind="component: { name: 'functions-panel' }, visible: activeTab() === 'functions'"></div>
       <!-- /ko -->
 
+      <!-- ko if: chatTabAvailable -->
+      <div data-bind="component: { name: 'chat-panel', params: { activeTab: activeTab } }, visible: activeTab() === 'chat'"></div>
+      <!-- /ko -->
+
       <!-- ko if: langRefTabAvailable -->Functions
       <div data-bind="component: { name: 'language-reference-panel' }, visible: activeTab() === 'langRef'"></div>
       <!-- /ko -->
@@ -3651,6 +3838,7 @@ from desktop.views import _ko
       var EDITOR_ASSISTANT_TAB = 'editorAssistant';
       var DASHBOARD_ASSISTANT_TAB = 'dashboardAssistant';
       var FUNCTIONS_TAB = 'functions';
+      var CHAT_TAB = 'chat';
       var SCHEDULES_TAB = 'schedules';
       var LANG_REF_TAB = 'langRef';
 
@@ -3664,6 +3852,7 @@ from desktop.views import _ko
         self.editorAssistantTabAvailable = ko.observable(false);
         self.dashboardAssistantTabAvailable = ko.observable(false);
         self.functionsTabAvailable = ko.observable(false);
+        self.chatTabAvailable = ko.observable(false);
         self.langRefTabAvailable = ko.observable(false);
         self.schedulesTabAvailable = ko.observable(false);
 
@@ -3700,6 +3889,8 @@ from desktop.views import _ko
             self.activeTab(EDITOR_ASSISTANT_TAB);
           } else if (self.functionsTabAvailable()) {
             self.activeTab(FUNCTIONS_TAB);
+          } else if (self.chatTabAvailable()) {
+            self.activeTab(CHAT_TAB);
           } else if (self.schedulesTabAvailable()) {
             self.activeTab(SCHEDULES_TAB);
           } else if (self.dashboardAssistantTabAvailable()) {
@@ -3711,6 +3902,7 @@ from desktop.views import _ko
 
         var updateContentsForType = function (type) {
           self.functionsTabAvailable(type === 'hive' || type === 'impala' || type === 'pig');
+          self.chatTabAvailable(type === 'hive' || type === 'impala' || type === 'pig');
           self.langRefTabAvailable(type === 'impala');
           self.editorAssistantTabAvailable((!window.IS_EMBEDDED || window.EMBEDDED_ASSISTANT_ENABLED) && (type === 'hive' || type === 'impala'));
           self.dashboardAssistantTabAvailable(type === 'dashboard');
@@ -3776,6 +3968,12 @@ from desktop.views import _ko
         self.switchTab(FUNCTIONS_TAB);
       };
 
+      RightAssistPanel.prototype.chatTabClick = function () {
+        var self = this;
+        self.lastActiveTabEditor(CHAT_TAB);
+        self.switchTab(CHAT_TAB);
+      };
+
       RightAssistPanel.prototype.langRefTabClick = function () {
         var self = this;
         self.lastActiveTabEditor(LANG_REF_TAB);