Explorar el Código

feat: 合并预定义问题部分代码

zhouyuhao hace 7 meses
padre
commit
ae95eac2a7

BIN
src/components/AIRobot/image/icon_ai_robot24_b@2x.png


BIN
src/components/AIRobot/image/icon_ai_robot36_b@2x.png


BIN
src/components/AIRobot/image/icon_ai_robot48_b@2x.png


BIN
src/components/AIRobot/image/icon_cancel_query_b@2x.png


BIN
src/components/AIRobot/image/icon_faq_b@2x.png


BIN
src/components/AIRobot/image/score_normal.png


+ 217 - 36
src/components/AIRobot/src/AIRobot.vue

@@ -1,49 +1,148 @@
 <script setup lang="ts">
-import { ref } from 'vue'
-import normalPng from '../image/score_normal.png'
+import { ref, onMounted } from 'vue'
+import normalPng from '../image/icon_ai_robot24_b@2x.png'
+import emitter from '@/utils/bus'
 
 const clickSrc = ref(normalPng)
 const visible = ref(false)
 const AIRobotHoverVisible = ref(false)
-const AIRobotClickVisible = ref(false)
 const clicked = ref(false)
+const isShowDefault = ref(false)
+const isShowAIRobotTop = ref(false)
+const DeQuestions = ref([
+  {
+    label: 'List shipments with ETA changes in the last 30 days.',
+    value: 'List shipments with ETA changes in the last 30 days.',
+    isLong: false
+  },
+  {
+    label: 'Shipments arriving in the next 7 days.',
+    value: 'Shipments arriving in the next 7 days.',
+    isLong: false
+  },
+  {
+    label: 'Show shipments delayed in the last 30 days.',
+    value: 'Show shipments delayed in the last 30 days.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with milestone updates in the last 7 days.',
+    value: 'List shipments with milestone updates in the last 7 days.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with milestone in the last 7 days2sdsa.',
+    value: 'List shipments with milestone in the last 7 days2sdsa.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with milestone updates 7 days3fef.',
+    value: 'List shipments with milestone updates 7 days3fef.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with ETA changes in the last 30 days11111111111111111111111111111111111.',
+    value: 'List shipments with ETA changes in the last 30 days11111111111111111111111111111111111.',
+    isLong: true
+  },
+  {
+    label: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111122.',
+    value: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111122.',
+    isLong: true
+  },
+  {
+    label: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111133.',
+    value: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111133.',
+    isLong: true
+  },
+])
+const itemGroups = ref([]);
+
 // 鼠标hover AIRobot图标
 const AvatarMouseEnter = () => {
-  if (!clicked.value) {
+  if (clicked.value) {
     AIRobotHoverVisible.value = true
     visible.value = true
   }
 }
 // 鼠标move AIRobot图标
 const AvatarMouseLeave = () => {
-  if (!clicked.value) {
+  if (clicked.value) {
     visible.value = false
     AIRobotHoverVisible.value = false
   }
 }
+const emit = defineEmits(['AvatarClick'])
 // 点击AIRobot图标
 const AvatarClick = () => {
+  clicked.value = true
   AIRobotHoverVisible.value = false
-  if(AIRobotClickVisible.value == true && visible.value) {
-    AIRobotClickVisible.value = false
-    visible.value = false
-    clicked.value = false
-  } else {
-    visible.value = true 
-    AIRobotClickVisible.value = true
-    clicked.value = true
+  isShowDefault.value = false
+  isShowAIRobotTop.value = false
+  emit('AvatarClick')
+}
+// 隐藏上方弹窗
+const HideAIRobotTop = () => {
+  isShowDefault.value = false
+}
+
+// 隐藏上方弹窗
+const HideAIRobotTopTwo = () => {
+  isShowAIRobotTop.value = false
+}
+
+// 随机显示方法
+const prepareGroups = () => {
+  const groups = [];
+  let currentGroup = [];
+  let currentHeight = 0;
+
+  DeQuestions.value.forEach(item => {
+    const itemHeight = item.isLong ? 2 : 1;
+    
+    if (currentHeight + itemHeight > 4) {
+      groups.push(currentGroup);
+      currentGroup = [];
+      currentHeight = 0;
+    }
+    
+    currentGroup.push(item);
+    currentHeight += itemHeight;
+  });
+
+  // 添加最后一组
+  if (currentGroup.length > 0) {
+    groups.push(currentGroup);
   }
+
+  itemGroups.value = groups;
 }
-const handlePopoverHide = () => {
-  clicked.value = false
-  AIRobotHoverVisible.value = false
-  AIRobotClickVisible.value = false
+
+const isShowLogin = () => {
+  isShowDefault.value = true
+  setTimeout(() => {
+    isShowDefault.value = false
+    isShowAIRobotTop.value = true
+  }, 5000);
 }
+
+onMounted(() => {
+  prepareGroups()
+  emitter.on('login-success', isShowLogin);
+});
+
+onUnmounted(() => {
+  emitter.off('login-success', isShowLogin);
+});
+
+defineExpose({
+  isShowLogin
+})
 </script>
 <template>
   <!-- 上方显示的弹窗 -->
-  <div class="AIRobot-top">
-    <div class="flex_end">
+  <div class="AIRobot-top" v-if="isShowDefault">
+    <div class="flex_end" @click="HideAIRobotTop">
       <div class="icon flex_center">
         <span class="iconfont_icon icon_dark">
             <svg class="iconfont" aria-hidden="true">
@@ -52,19 +151,55 @@ const handlePopoverHide = () => {
           </span>
       </div>
     </div>
-    <div class="dialogue_title">
-      Hi! I'm your Freight Assistant, always on call
+    <div class="flex_title">
+      <div class="AIAvator">
+        <img width="40px" src="../image/icon_ai_robot36_b@2x.png" />
+      </div>
+      <div class="dialogue_title">
+        Hi! I'm your Freight Assistant, always on call
+      </div>
     </div>
-    <div class="dialogue_content">
-      <div class="dialogue_content_title">
-        <div class="dialogue_title_left">
-          Frequently Asked Questions
-        </div>
-        <div class="dialogue_title_right">
-          Refresh Questions
+    <div class="flex_end">
+      <div class="dialogue_content ">
+        <div class="dialogue_content_title">
+          <div class="dialogue_title_left">
+            <img src="../image/icon_faq_b@2x.png" width="24px" />
+            Frequently Asked Questions
+          </div>
         </div>
+        <el-carousel class="carousel" :autoplay="false" height="190px" style="width: 452px;" >
+          <el-carousel-item 
+            v-for="(group, index) in itemGroups "
+            :key="index"
+          >
+            <div class="dialogue_container">
+              <div 
+                class="dialogue_content_item"
+                v-for="item in group"
+                :key="item.label"
+                :class="{ 'long_item': item.isLong }"
+              >
+                {{ item.label }}
+              </div>
+            </div>
+          </el-carousel-item>
+        </el-carousel>
+      </div>
+    </div>
+  </div>
+  <div class="AIRobot-top" v-if="isShowAIRobotTop">
+    <div class="flex_end" @click="HideAIRobotTopTwo">
+      <div class="icon flex_center">
+        <span class="iconfont_icon icon_dark">
+            <svg class="iconfont" aria-hidden="true">
+              <use xlink:href="#icon-icon_reject_b"></use>
+            </svg>
+          </span>
       </div>
     </div>
+    <div class="dialogue_title">
+      Hi! I'm your Freight Assistant, always on call
+    </div>
   </div>
   <!-- 悬浮icon -->
   <div class="AIRobot flex_center">
@@ -72,15 +207,12 @@ const handlePopoverHide = () => {
       :visible="visible"
       placement="top-end"
       width="auto"
-      @hide="handlePopoverHide"
     >
       <template #reference>
-        <el-avatar @click="AvatarClick" @mouseenter="AvatarMouseEnter" @mouseleave="AvatarMouseLeave" :size="46" shape="square" :src="clickSrc" />
+        <el-avatar @click="AvatarClick" @mouseenter="AvatarMouseEnter" @mouseleave="AvatarMouseLeave" :size="46" shape="square" class="avatar_bg" :src="clickSrc" />
       </template>
       <!-- hover时显示的对话框 -->
       <div v-if="AIRobotHoverVisible" class="AIRobot_dialog">Continue the conversation</div>
-      <!-- click时显示的对话框 -->
-      <div v-if="AIRobotClickVisible" class="AIRobot_dialog">Continue the conversation  156468482</div>
     </el-popover>
   </div>
 </template>
@@ -98,19 +230,24 @@ const handlePopoverHide = () => {
   display: flex;
   justify-content: end;
 }
+.flex_title {
+  display: flex;
+  align-items: center;
+  width: 500px;
+}
 .AIRobot-top {
   position: absolute;
   z-index: 2013;
-  right: 20px;
-  bottom: 250px;
+  right: 50px;
+  bottom: 230px;
 }
 .dialogue_content_title {
   display: flex;
   align-items: center;
   justify-content: space-between;
+  padding-left: 8px;
 }
 .dialogue_title_left {
-  margin-right: 80px;
   background: linear-gradient(90deg, #A71549 1.77%, #06256E 46.77%);
   -webkit-background-clip: text;
   background-clip: text;
@@ -118,12 +255,22 @@ const handlePopoverHide = () => {
   font-size: 14px;
   font-weight: 700;
 }
+.dialogue_title_right {
+  color: var(--color-theme);
+  cursor: pointer;
+  user-select: none;
+}
+.icon_theme {
+  fill: var(--color-theme);
+  cursor: pointer;
+}
 .icon {
   width: 24px;
   height: 24px;
   background-color: var(--management-bg-color);
   box-shadow: -2px 2px 12px rgba(0, 0, 0, 15%);
   border-radius: 6px;
+  cursor: pointer;
 }
 .AIRobot {
   width: 64px;
@@ -151,7 +298,41 @@ const handlePopoverHide = () => {
 }
 .dialogue_content {
   background: linear-gradient(92deg, #EAECFF 1.33%, #F1E3FB 99.63%);
-  padding: 8px;
+  padding: 8px 0 0 0;
   border-radius: 12px;
 }
+.AIAvator {
+  width: 40px;
+  height: 40px;
+  background: radial-gradient(50% 43% at 50% 54.79%, #D5B4F3 0%, #FFF9FC 100%);
+  border-radius: 12px;
+  margin-right: 8px;
+}
+.dialogue_container {
+  width: 420px;
+  height: 156px;
+  border-radius: 12px;
+  border: 1px solid #FFF;
+  padding: 8px;
+  background: rgba(255, 255, 255, 0.50);
+}
+.dialogue_content_item {
+  width: 404px;
+  height: 32px;
+  padding: 5.5px 8px;
+  border-radius: 6px;
+  background-color: var(--color-dialogue-bg);
+  margin-bottom: 4px;
+  display: flex;
+  align-items: center;
+  word-break: break-word;
+  overflow: hidden;
+  transition: all 0.3s ease;
+}
+.itemLable { 
+  width: 100%;
+}
+.long_item {
+  height: 64px;
+}
 </style>

+ 37 - 0
src/styles/elementui.scss

@@ -795,3 +795,40 @@ div .DaterangeClass {
 div .el-radio__label {
   width: 100%;
 }
+
+div .avatar_bg {
+  background-color: transparent !important;
+}
+div .carousel .el-carousel__indicator--horizontal {
+  padding: 4px 8px;
+}
+div .carousel .el-carousel__button {
+  width: 6px;
+  height: 6px;
+  border-radius: 50%;
+  background-color: var(--color-system-card-bg);
+  opacity: 1;
+}
+div .carousel .el-carousel__indicator.is-active button {
+  background-color: var(--color-theme);
+}
+div .carousel .el-carousel__item--card, .el-carousel__item.is-animating {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding-bottom: 15px;
+}
+div .carousel .el-carousel__arrow {
+  opacity: 1;
+  background-color: var(--color-system-card-bg);
+}
+div .carousel .el-carousel__arrow--left {
+  left: 0;
+}
+div .carousel .el-carousel__arrow--right {
+  right: 0;
+}
+div .carousel .el-icon {
+  fill: black;
+  color: black;
+}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/styles/icons/iconfont.js


BIN
src/styles/icons/iconfont.ttf


BIN
src/styles/icons/iconfont.woff


BIN
src/styles/icons/iconfont.woff2


+ 4 - 0
src/styles/theme-g.scss

@@ -79,4 +79,8 @@
   --color-system-card-bg:#2B2F36;
   --color-system-border-1: #3F434A;
   --color-system-input-border: #656f7d;
+
+  
+  // AI Robot
+  --color-dialogue-bg: rgba(255,255,255,0.13);
 }

+ 2 - 0
src/styles/theme.scss

@@ -281,6 +281,8 @@
   --color-system-input-border: #e8eaee;
   --color-personal-preference-bg: #f5f7fa;
 
+  // AI Robot
+  --color-dialogue-bg: #fff;
   --color-ai-chat-header-bg-gradient-begin: #eaecff;
   --color-ai-chat-header-bg-gradient-end: #fefdff;
   --color-ai-user-bubble-bg-gradient-begin: #ffede6;

+ 7 - 2
src/views/AIRobotChat/src/AIRobotChat.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import AutoResizeTextarea from './components/AutoResizeTextarea.vue'
 import LoadingDots from './components/LoadingDots.vue'
+import AIQuestions from './components/AIQuestions.vue'
 import userBubbleLight from './image/userBubbleLight.png'
 import userBubbleDark from './image/userBubbleDark.png'
 import robotBubbleLight from './image/robotBubbleLight.png'
@@ -162,8 +163,13 @@ const handleClose = () => {
           <span @click="handleClose" class="font_family icon-icon_collapsed__to_widget_b"></span>
         </div>
       </div>
+      <AIQuestions :modalSize="modalSize"></AIQuestions>
     </div>
-    <div class="chat-messages" ref="messagesRef">
+    <div
+      class="chat-messages"
+      ref="messagesRef"
+      :style="{ marginTop: modalSize === 'large' ? '81px' : '151px' }"
+    >
       <div
         class="message-item"
         :class="[
@@ -307,7 +313,6 @@ const handleClose = () => {
     display: flex;
     flex-direction: column;
     gap: 16px;
-    margin-top: 81px;
     padding: 0 16px;
     overflow: auto;
     .message-item {

+ 263 - 0
src/views/AIRobotChat/src/components/AIQuestions.vue

@@ -0,0 +1,263 @@
+<script setup lang="ts">
+import { ref, onMounted } from 'vue'
+
+const props = defineProps<{
+  modalSize: String
+}>()
+
+const DeQuestions = ref([
+  {
+    label: 'List shipments with ETA changes in the last 30 days.',
+    value: 'List shipments with ETA changes in the last 30 days.',
+    isLong: false
+  },
+  {
+    label: 'Shipments arriving in the next 7 days.',
+    value: 'Shipments arriving in the next 7 days.',
+    isLong: false
+  },
+  {
+    label: 'Show shipments delayed in the last 30 days.',
+    value: 'Show shipments delayed in the last 30 days.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with milestone updates in the last 7 days.',
+    value: 'List shipments with milestone updates in the last 7 days.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with milestone in the last 7 days2sdsa.',
+    value: 'List shipments with milestone in the last 7 days2sdsa.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with milestone updates 7 days3fef.',
+    value: 'List shipments with milestone updates 7 days3fef.',
+    isLong: false
+  },
+  {
+    label: 'List shipments with ETA changes in the last 30 days11111111111111111111111111111111111.',
+    value: 'List shipments with ETA changes in the last 30 days11111111111111111111111111111111111.',
+    isLong: true
+  },
+  {
+    label: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111122.',
+    value: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111122.',
+    isLong: true
+  },
+  {
+    label: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111133.',
+    value: 'List shipments with ETA changes in the last 30 days1111111111111111111111111111111111133.',
+    isLong: true
+  },
+])
+const itemGroups = ref([]);
+const pages = ref([]);
+// 随机显示方法
+const prepareGroups = () => {
+  const groups = [];
+  let currentGroup = [];
+  let currentHeight = 0;
+
+  DeQuestions.value.forEach(item => {
+    const itemHeight = item.isLong ? 2 : 1;
+    
+    if (currentHeight + itemHeight > 4) {
+      groups.push(currentGroup);
+      currentGroup = [];
+      currentHeight = 0;
+    }
+    
+    currentGroup.push(item);
+    currentHeight += itemHeight;
+  });
+
+  // 添加最后一组
+  if (currentGroup.length > 0) {
+    groups.push(currentGroup);
+  }
+
+  itemGroups.value = groups;
+}
+// 智能分页算法
+const generatePages = () => {
+  const result = [];
+  let currentPage = { row1: [], row2: [] };
+  let cursor = 0;
+  
+  while(cursor < DeQuestions.value.length) {
+    // 处理第一排
+    const currentItem = DeQuestions.value[cursor];
+    // 第一排逻辑
+    if(currentItem.isLong) {
+      // 长文本独占第一排
+      currentPage.row1.push(currentItem);
+      cursor++;
+    } else {
+      // 尝试取两个短文本
+      const nextItem = DeQuestions.value[cursor + 1];
+      if(nextItem && !nextItem.isLong) {
+        currentPage.row1.push(currentItem, nextItem);
+        cursor += 2;
+      } else {
+        currentPage.row1.push(currentItem);
+        cursor++;
+      }
+    }
+
+    // 处理第二排
+    const remaining = DeQuestions.value.slice(cursor);
+    if(remaining.length > 0) {
+      const secondItem = remaining[0];
+      
+      if(secondItem.isLong) {
+        currentPage.row2.push(secondItem);
+        cursor++;
+      } else {
+        const nextSecondItem = remaining[1];
+        if(nextSecondItem && !nextSecondItem.isLong) {
+          currentPage.row2.push(secondItem, nextSecondItem);
+          cursor += 2;
+        } else {
+          currentPage.row2.push(secondItem);
+          cursor++;
+        }
+      }
+    }
+
+    // 保存当前页
+    result.push(currentPage);
+    
+    // 重置页面
+    currentPage = { row1: [], row2: [] };
+  }
+  pages.value = result.filter(p => p.row1.length > 0);
+  console.log(pages.value)
+}
+onMounted(() => {
+  prepareGroups()
+  generatePages()
+});
+</script>
+<template>
+  <div class="flex_center">
+    <div class="dialogue_content ">
+      <div class="dialogue_content_title">
+        <div class="dialogue_title_left">
+          <img class="dialogue_title_left_img" src="../image/icon_ai_robot48_b@2x.png" width="48px" />
+          <div class="dialogue_title_left_text">Frequently Asked Questions</div>
+        </div>
+      </div>
+      <el-carousel v-if="props.modalSize === 'large'"  class="carousel large_carousel" :autoplay="false" height="115px" >
+        <el-carousel-item 
+          v-for="(page, index) in pages "
+          :key="index"
+        >
+          <div class="dialogue_container dialogue_container_large">
+            <div class="double-row-layout">
+              <!-- 第一排 -->
+              <div class="row first-row">
+                <template v-for="item in page.row1" :key="item.id">
+                  <div class="dialogue_content_item" :class="{ 'long-item': item.isLong }">
+                    {{ item.label }}
+                  </div>
+                </template>
+              </div>
+              <!-- 第二排 -->
+              <div class="row second-row">
+                <template v-for="item in page.row2" :key="item.id">
+                  <div class="dialogue_content_item" :class="{ 'long-item': item.isLong }">
+                    {{ item.label }}
+                  </div>
+                </template>
+              </div>
+            </div>
+          </div>
+        </el-carousel-item>
+      </el-carousel>
+      <el-carousel v-else  class="carousel small_carousel" :autoplay="false" height="190px" >
+        <el-carousel-item 
+          v-for="(group, index) in itemGroups "
+          :key="index"
+        >
+          <div class="dialogue_container">
+            <div 
+              class="dialogue_content_item"
+              v-for="item in group"
+              :key="item.label"
+              :class="{ 'long_item': item.isLong }"
+            >
+              {{ item.label }}
+            </div>
+          </div>
+        </el-carousel-item>
+      </el-carousel>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.dialogue_content {
+  background: linear-gradient(117deg, var(--1-gradient-ai-robot-0, #B5FEF3) 4.31%, var(--1-gradient-ai-robot-15, #F9EEEC) 14.24%, var(--1-gradient-ai-robot-38, #FBD3EE) 29.71%, var(--1-gradient-ai-robot-59, #DDD5F7) 43.72%, var(--1-gradient-ai-robot-83, #C8F4F3) 59.35%, var(--1-gradient-ai-robot-100, #CADFF8) 70.56%);
+}
+.dialogue_title_left {
+  position: relative;
+}
+.dialogue_title_left_img {
+  position: absolute;
+  top: -22px;
+}
+.dialogue_title_left_text {
+  background: linear-gradient(90deg, #A71549 1.77%, #06256E 46.77%);
+  -webkit-background-clip: text;
+  background-clip: text;
+  color: transparent;
+  font-size: 14px;
+  font-weight: 700;
+  margin: 5px 0 0 55px;
+}
+.small_carousel {
+  width: 452px;
+}
+.large_carousel {
+  width: 968px;
+}
+.double-row-layout {
+  height: 100%;
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+}
+.row {
+  flex: 1;
+  display: flex;
+  min-height: 0; /* 防止内容溢出 */
+}
+.long-item {
+  grid-column: span 2;
+}
+.dialogue_container_large {
+  width: 936px;
+  height: 84px;
+}
+.dialogue_content_item {
+  width: 100%;
+  height: 32px;
+  padding: 5.5px 8px;
+  border-radius: 6px;
+  background-color: var(--color-dialogue-bg);
+  margin-right: 4px;
+  word-break: break-word;
+  overflow: hidden;
+  display: flex;
+  align-items: center;
+  justify-content: start;
+  text-align: center;
+  min-width: 0; /* 防止文本溢出 */
+}
+:deep(.el-carousel__item--card, .el-carousel__item.is-animating) {
+  padding-bottom: 0 !important;
+}
+</style>
+

BIN
src/views/AIRobotChat/src/image/icon_ai_robot36_b@2x.png


BIN
src/views/AIRobotChat/src/image/icon_ai_robot48_b@2x.png


BIN
src/views/AIRobotChat/src/image/icon_faq_b@2x.png


+ 5 - 1
src/views/Layout/src/LayoutView.vue

@@ -22,6 +22,10 @@ const handleColseRobotChat = () => {
 const onClick = () => {
   isShowAIRobotChat.value = true
 }
+
+const AvatarClick = () => {
+  isShowAIRobotChat.value = true
+}
 </script>
 <template>
   <el-container class="layout-container">
@@ -52,7 +56,7 @@ const onClick = () => {
         <router-view />
       </el-main>
     </el-container>
-    <!-- <AIRobot></AIRobot> -->
+    <AIRobot @AvatarClick="AvatarClick"></AIRobot>
     <AIRobotChat v-if="isShowAIRobotChat" @close="handleColseRobotChat"></AIRobotChat>
     <ScoringGrade></ScoringGrade>
   </el-container>

+ 5 - 0
src/views/Layout/src/components/Menu/MenuView.vue

@@ -2,6 +2,7 @@
 import { useRoute, useRouter } from 'vue-router'
 import { useUserStore } from '@/stores/modules/user'
 import { CaretRight } from '@element-plus/icons-vue'
+import emitter from '@/utils/bus'
 
 const route = useRoute()
 const router = useRouter()
@@ -90,6 +91,10 @@ const changeRouter = (path: any) => {
   }
   sessionStorage.removeItem('trackingTablePageInfo')
   sessionStorage.removeItem('bookingTablePageInfo')
+  if (localStorage.getItem('loginAI')) {
+    localStorage.removeItem('loginAI')
+    emitter.emit('login-success');
+  }
   isVisible.value = false
   emits('changeVisible', isVisible.value)
   isVisible.value = false

+ 1 - 0
src/views/Login/src/loginView.vue

@@ -212,6 +212,7 @@ const handleResult = (res: any) => {
       })
     }
     localStorage.setItem('user_type', res.data.user_info.user_type)
+    localStorage.setItem('loginAI', 'loginAI')
     userStore.setUserInfo(res.data?.user_info || {})
     router.push('/')
   } else if (res.code === 400) {

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio