Преглед на файлове

feat:首页新增快捷搜索,新增授权管理前端静态页面

hanyang преди 1 година
родител
ревизия
e3b57997f5

+ 4 - 0
public/i18n/lang-en.json

@@ -524,6 +524,7 @@
     "menuTitle": "System Settings",
     "global": "General configuration",
     "password": "Change Password",
+    "authorization": "Authorization Settings",
     "current_password": "Current Password",
     "placeholder_cur_password": "Please enter the original password",
     "new_password": "New Password",
@@ -546,5 +547,8 @@
     "platform_introduce_placeholder": "Please enter the platform introduction",
     "update_success": "Password change successful",
     "update_fail": "Password change failed"
+  },
+  "auth": {
+    "modelName": "System Activation"
   }
 }

+ 4 - 0
public/i18n/lang-zh.json

@@ -525,6 +525,7 @@
     "menuTitle": "系统设置",
     "global": "通用配置",
     "password": "修改密码",
+    "authorization": "授权管理",
     "current_password": "当前密码",
     "placeholder_cur_password": "请输入原密码",
     "new_password": "新密码",
@@ -547,5 +548,8 @@
     "platform_introduce_placeholder": "请输入平台介绍",
     "update_success": "修改密码成功",
     "update_fail": "修改密码失败"
+  },
+  "auth": {
+    "modelName": "系统激活"
   }
 }

+ 28 - 0
src/App.vue

@@ -1,11 +1,15 @@
 <template>
   <a-config-provider :locale="locale">
+    <a-alert class="alert_txt" type="warning" v-if="show_warning"
+      >您的软件试用期即将到期,输入授权密钥方可正常使用! <span @click="toAuth">去授权 >></span></a-alert
+    >
     <router-view />
   </a-config-provider>
 </template>
 
 <script setup>
 import { ref, computed } from 'vue';
+import { useRouter } from 'vue-router';
 import { useLocaleStore } from './base/store/use-locale';
 
 /**
@@ -21,10 +25,34 @@ const locales = {
 
 const localStore = useLocaleStore();
 
+const router = useRouter();
 /**
  * 多语言
  */
 const locale = computed(() => {
   return locales[localStore.value] || zhCN;
 });
+
+const show_warning = ref(false);
+/**
+ *去授权
+ * */
+const toAuth = () => {
+  router.push({
+    path: '/auth'
+  });
+};
 </script>
+<style scoped>
+.alert_txt {
+  position: absolute;
+  width: 500px;
+  top: 60px;
+  left: calc(50% - 250px);
+  z-index: 9999;
+  span {
+    cursor: pointer;
+    color: var(--color-link-1);
+  }
+}
+</style>

+ 114 - 0
src/modules/auth/FormItem.vue

@@ -0,0 +1,114 @@
+<template>
+  <div class="form-title">
+    {{ $t('auth.modelName') }}
+  </div>
+  <a-form
+    ref="ref_form"
+    :model="form"
+    :style="{ width: 'calc(100% - 40px)' }"
+    layout="horizontal"
+    @submit-success="handleSubmit"
+  >
+    <a-form-item field="username" label="版本类型">
+      <a-input v-model="form.version" :placeholder="$t('login.usernameTips')"> </a-input>
+    </a-form-item>
+    <a-form-item field="username" label="激活状态">
+      <a-input v-model="form.status" :placeholder="$t('login.usernameTips')"> </a-input>
+    </a-form-item>
+    <a-form-item field="username" label="请求码">
+      <a-input v-model="form.request_code" :placeholder="$t('login.usernameTips')"> </a-input>
+    </a-form-item>
+    <a-form-item field="username" label="授权密钥">
+      <a-textarea
+        v-model="form.auth_key"
+        placeholder="Please enter something"
+        :auto-size="{
+          minRows: 2,
+          maxRows: 5
+        }"
+      />
+    </a-form-item>
+    <div style="margin-top: 30px">
+      <a-button v-if="!form_type" class="submit-btn" type="primary" html-type="submit" :loading="loading">
+        激活
+      </a-button>
+    </div>
+  </a-form>
+</template>
+
+<script setup>
+import { ref, reactive, getCurrentInstance } from 'vue';
+import { useRouter } from 'vue-router';
+
+import { Message } from '../../3rd-libs/arco-vue-libs';
+
+const router = useRouter();
+
+const ref_form = ref();
+const form = reactive({
+  version: '灵慧云智大模型平台',
+  status: '未激活', // 非必填
+  request_code: 'ASDFGHJDFGSDFSDEF',
+  auth_key: 'ASDFGHJDFGSDFSDEFASDFGHJDFGSDFSDEF'
+});
+
+const handleSubmit = (data) => {
+  loading.value = true;
+};
+</script>
+<style scoped>
+.form-title {
+  position: absolute;
+  top: 50px;
+  line-height: 42px;
+  font-size: 30px;
+  font-weight: 600;
+  color: var(--color-text-1);
+}
+
+.submit-btn {
+  width: 100%;
+  height: 54px;
+  background-color: rgb(var(--primary-6));
+  color: var(--color-bg-1);
+  font-size: 20px;
+  border-radius: 3px;
+}
+
+.submit-btn:hover {
+  background-color: rgba(var(--primary-6), 0.8);
+  color: var(--color-bg-1);
+}
+
+.tips-register {
+  position: absolute;
+  right: 20px;
+  bottom: 70px;
+  font-size: 20px;
+  color: var(--color-border-3);
+}
+.tips-login {
+  position: absolute;
+  right: 20px;
+  bottom: 30px;
+  font-size: 20px;
+  color: var(--color-border-3);
+}
+
+.reg-link {
+  color: var(--color-link-1);
+  text-decoration: underline;
+}
+.arco-form {
+  margin-top: 90px;
+}
+
+.arco-form-item-label-col {
+  padding: 0px;
+}
+
+.arco-input-wrapper {
+  background-color: var(--color-bg-1);
+  border-color: var(--color-border-2);
+}
+</style>

+ 1 - 2
src/modules/conversation-chat/DialogCommonUsed.vue

@@ -50,7 +50,6 @@ const toSend = (text) => {
 const handleGlobalClick = (event) => {
   // 检查点击是否发生在 searchListDialog 和 usedItemRefs 以外的区域
   const clickedOutsideUsedItems = !usedItemRefs.value.some((ref) => ref.contains(event.target));
-  console.log(clickedOutsideUsedItems);
   if (searchListDialog.value && !searchListDialog.value.contains(event.target) && clickedOutsideUsedItems) {
     current_List_key.value = ''; // 隐藏 UsedSearchList
   }
@@ -58,7 +57,7 @@ const handleGlobalClick = (event) => {
 // 添加全局点击事件监听
 onMounted(() => {
   // 确保 DOM 更新完成后再添加事件监听
-  // document.addEventListener('click', handleGlobalClick);
+  document.addEventListener('click', handleGlobalClick, true);
 });
 
 // 移除全局点击事件监听

+ 11 - 1
src/modules/intelligent/CardDefault.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="card-default">
+  <div class="card-default" v-hasPermi="permi_map[type]">
     <div class="header">
       <img class="icon" :src="getIconIntelligent(img_src)" alt="" />
       <div class="title">{{ name }}</div>
@@ -33,8 +33,18 @@ const props = defineProps({
   labels: {
     type: String,
     default: 'LLM,TEXT'
+  },
+  type: {
+    type: String
   }
 });
+
+const permi_map = {
+  'agent-dialog': 'system:intelligent:agentDialog',
+  'advanced-chat': 'system:intelligent:advanceChat',
+  'agent-chat': 'system:intelligent:agentChat',
+  workflow: 'system:intelligent:workflow'
+};
 </script>
 <style scoped lang="css">
 .card-default {

+ 1 - 0
src/modules/intelligent/ModalAddIntel.vue

@@ -19,6 +19,7 @@
         :name="item.name"
         :description="item.description"
         :labels="item.labels"
+        :type="item.type"
       >
         <template #footer>
           <a-button class="add-btn" @click="addNewIntelligent(item)">

+ 12 - 12
src/modules/intelligent/rgflow/AgentConfig.vue

@@ -295,7 +295,7 @@
                   </a-space>
                 </a-form-item>
                 <!-- 最大token数 -->
-                <a-form-item :label="$t('management.rg_config.max_token_count')">
+                <!-- <a-form-item :label="$t('management.rg_config.max_token_count')">
                   <a-switch size="small" v-model="max_tokens" />
                   <a-space direction="vertical" size="large">
                     <a-slider
@@ -311,7 +311,7 @@
                       show-input
                     />
                   </a-space>
-                </a-form-item>
+                </a-form-item> -->
               </a-form>
             </div>
           </a-tab-pane>
@@ -564,10 +564,10 @@ const handleBeforeOk = async (done) => {
       title = t('management.edit_success');
     }
 
-    if (!max_tokens.value) {
-      //formNew.llm_setting.max_tokens = '';
-      delete formNew.llm_setting.max_tokens;
-    }
+    // if (!max_tokens.value) {
+    //   //formNew.llm_setting.max_tokens = '';
+    //   delete formNew.llm_setting.max_tokens;
+    // }
     setLoading(true);
     try {
       const res = await createRgFlow(formNew);
@@ -609,12 +609,12 @@ const handleBeforeOk = async (done) => {
 const editClick = (data) => {
   visible.value = true;
   nextTick(() => {
-    if (props.formData.llm_setting.max_tokens == '') {
-      max_tokens.value = false;
-      delete props.formData.llm_setting.max_tokens;
-    } else {
-      max_tokens.value = true;
-    }
+    // if (props.formData.llm_setting.max_tokens == '') {
+    //   max_tokens.value = false;
+    //   delete props.formData.llm_setting.max_tokens;
+    // } else {
+    //   max_tokens.value = true;
+    // }
     Object.assign(form, props.formData);
     form.vector_similarity_weight = 1 - form.vector_similarity_weight;
   });

+ 101 - 0
src/router/Login.vue

@@ -0,0 +1,101 @@
+<template>
+  <div class="login">
+    <div class="login-logo">
+      <img class="logo-img" src="/logo.png" alt="logo" />
+      <div class="logo-title">{{ platform_name }}</div>
+    </div>
+    <div class="login-section">
+      <div class="intro">
+        <div class="intro-title">{{ platform_name }}</div>
+        <div class="intro-title">{{ platform_introduce }}</div>
+        <img src="../assets/image/login/login_group.png" alt="" />
+      </div>
+      <div class="login-form">
+        <FormItem />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue';
+import FormItem from '../modules/login/FormItem.vue';
+import { getSystemInfo } from '../apis/login';
+import { usePlatformInformation } from '../base/store/use-platform-information';
+
+const platformInformation = usePlatformInformation();
+
+const platform_name = ref(platformInformation.platform_name);
+const platform_introduce = ref(platformInformation.platform_introduce);
+
+const getSystemInfoFun = async () => {
+  try {
+    const res = await getSystemInfo();
+    console.log(res);
+    if (res.code / 1 === 200) {
+      platformInformation.updatePlatformInformation(res.data.title, res.data.desc);
+    }
+  } catch (e) {
+    console.log(e);
+  }
+};
+onMounted(() => {
+  // TODO: 获取系统名称和系统描述
+  getSystemInfoFun();
+});
+</script>
+<style scoped lang="css">
+.login {
+  width: 100vw;
+  height: 100vh;
+  background: url('../assets/image/login/bg.png') no-repeat;
+  background-size: cover;
+}
+.login-logo {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding: 30px;
+}
+.logo-img {
+  width: 50px;
+}
+.logo-title {
+  margin-left: 20px;
+  font-size: 24px;
+  font-weight: 600;
+  color: var(--color-text-1);
+}
+.login-section {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+  gap: 100px;
+  height: calc(100% - 115px);
+}
+.intro {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  color: var(--color-text-1);
+}
+.intro-title {
+  font-size: 38px;
+  font-weight: 600;
+}
+.login-form {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 20px;
+  width: 500px;
+  height: 512px;
+  background-color: var(--color-bg-1);
+  border-radius: 10px;
+  box-shadow: 0 0 1px var(--color-border-4);
+}
+</style>

+ 3 - 1
src/router/index.js

@@ -24,10 +24,12 @@ const whiteList = ['/login', '/reg', '/denied', '/chat/voice'];
  * 这些路由无需权限判断,但是需要用户登录
  */
 const require_login_paths = [
+  '/auth',
   '/settings',
   // '/settings/profile',
   '/settings/global',
-  '/settings/password'
+  '/settings/password',
+  '/settings/auth'
   // '/settings/phone',
   // '/settings/email'
 ];

+ 99 - 0
src/router/route copy.js

@@ -0,0 +1,99 @@
+import Home from '../views/Home.vue';
+
+/**
+ * 路由表配置
+ */
+export const systemRoutes = [
+  { path: '/', component: Home, redirect: '/chat/qa' },
+  // { path: '/', component: Home, redirect: '/xiaoshu' },
+  // { path: '/', component: Home },
+
+  // 登录与注册 白名单页面
+  { path: '/auth', component: () => import('../views/Auth.vue') },
+  { path: '/login', component: () => import('../views/Login.vue') },
+  { path: '/reg', component: () => import('../views/Register.vue') },
+
+  { path: '/chat/voice', component: () => import('../views/ConversationVoice.vue') },
+
+  /**
+   * 设置
+   */
+  {
+    path: '/settings',
+    component: () => import('../views/Settings.vue'),
+    children: [
+      {
+        path: 'profile',
+        component: () => import('../views/SettingsProfile.vue')
+      },
+      // 修改密码
+      {
+        // path: '/settings/password',
+        path: 'password',
+        component: () => import('../views/SettingsPassword.vue')
+      },
+      {
+        path: 'phone',
+        component: () => import('../views/SettingsPhone.vue')
+      },
+      {
+        path: 'email',
+        component: () => import('../views/SettingsEmail.vue')
+      },
+      // 通用配置
+      {
+        path: 'global',
+        component: () => import('../views/SettingsGlobal.vue')
+      },
+      // 授权设置
+      {
+        path: 'auth',
+        component: () => import('../views/SettingsAuth.vue')
+      }
+    ]
+  },
+
+  // 错误页面
+  { path: '/denied', component: () => import('../views/Denied.vue') }
+
+  // // 会话
+  // // { path: '/chat', redirect: '/chat/qa' },
+  // { path: '/chat', component: () => import('../views/Conversation.vue') },
+  // { path: '/chat/qa', component: () => import('../views/ConversationQA.vue') },
+  // { path: '/chat/history', component: () => import('../views/ConversationHistory.vue') },
+  // { path: '/chat/board', component: () => import('../views/ConversationBoard.vue') },
+
+  // // // 知识库
+  // { path: '/knowledge', component: () => import('../views/Knowledge.vue') },
+  // { path: '/knowledge/detail', component: () => import('../views/KnowledgeDetail.vue') },
+  // // 模型
+  // { path: '/model', component: () => import('../views/Model.vue') },
+  // // Agent
+  // { path: '/agent', component: () => import('../views/Agent.vue') },
+  // // 智能体
+  // { path: '/intelligent', component: () => import('../views/Intelligent.vue') },
+  // // dify智能体详情
+  // { path: '/intelligent/detail', component: () => import('../views/difyDetail.vue') },
+
+  // // 权限管理
+  // {
+  //   path: '/permission',
+  //   component: () => import('../views/layout/LayoutPermission.vue'),
+  //   children: [
+  //     { path: '/permission/account', component: () => import('../views/PermissionAccount.vue') },
+  //     { path: '/permission/org', component: () => import('../views/PermissionOrganization.vue') },
+  //     { path: '/permission/resource', component: () => import('../views/PermissionResource.vue') },
+  //     { path: '/permission/role', component: () => import('../views/PermissionRole.vue') },
+  //     { path: '/permission/group', component: () => import('../views/PermissionGroup.vue') }
+  //   ]
+  // },
+
+  // // 个人中心
+  // { path: '/profile', component: () => import('../views/Profiles.vue') },
+  // { path: '/setting', component: () => import('../views/Settings.vue') },
+
+  // { path: '/xiaoshu', component: () => import('../views/Xiaoshu.vue') },
+
+  // { path: '/ragchat', component: () => import('../views/RagFlowChat.vue') },
+  // { path: '/about', component: () => import('../views/About.vue') }
+];

+ 6 - 0
src/router/route.js

@@ -9,6 +9,7 @@ export const systemRoutes = [
   // { path: '/', component: Home },
 
   // 登录与注册 白名单页面
+  { path: '/auth', component: () => import('../views/Auth.vue') },
   { path: '/login', component: () => import('../views/Login.vue') },
   { path: '/reg', component: () => import('../views/Register.vue') },
 
@@ -43,6 +44,11 @@ export const systemRoutes = [
       {
         path: 'global',
         component: () => import('../views/SettingsGlobal.vue')
+      },
+      // 授权设置
+      {
+        path: 'auth',
+        component: () => import('../views/SettingsAuth.vue')
       }
     ]
   },

+ 101 - 0
src/views/Auth.vue

@@ -0,0 +1,101 @@
+<template>
+  <div class="login">
+    <div class="login-logo">
+      <img class="logo-img" src="/logo.png" alt="logo" />
+      <div class="logo-title">{{ platform_name }}</div>
+    </div>
+    <div class="login-section">
+      <div class="intro">
+        <div class="intro-title">{{ platform_name }}</div>
+        <div class="intro-title">{{ platform_introduce }}</div>
+        <img src="../assets/image/login/login_group.png" alt="" />
+      </div>
+      <div class="login-form">
+        <FormItem />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue';
+import FormItem from '../modules/auth/FormItem.vue';
+import { getSystemInfo } from '../apis/login';
+import { usePlatformInformation } from '../base/store/use-platform-information';
+
+const platformInformation = usePlatformInformation();
+
+const platform_name = ref(platformInformation.platform_name);
+const platform_introduce = ref(platformInformation.platform_introduce);
+
+const getSystemInfoFun = async () => {
+  try {
+    const res = await getSystemInfo();
+    console.log(res);
+    if (res.code / 1 === 200) {
+      platformInformation.updatePlatformInformation(res.data.title, res.data.desc);
+    }
+  } catch (e) {
+    console.log(e);
+  }
+};
+onMounted(() => {
+  // TODO: 获取系统名称和系统描述
+  getSystemInfoFun();
+});
+</script>
+<style scoped lang="css">
+.login {
+  width: 100vw;
+  height: 100vh;
+  background: url('../assets/image/login/bg.png') no-repeat;
+  background-size: cover;
+}
+.login-logo {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding: 30px;
+}
+.logo-img {
+  width: 50px;
+}
+.logo-title {
+  margin-left: 20px;
+  font-size: 24px;
+  font-weight: 600;
+  color: var(--color-text-1);
+}
+.login-section {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  justify-content: center;
+  gap: 100px;
+  height: calc(100% - 115px);
+}
+.intro {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  color: var(--color-text-1);
+}
+.intro-title {
+  font-size: 38px;
+  font-weight: 600;
+}
+.login-form {
+  position: relative;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 20px;
+  width: 500px;
+  height: 512px;
+  background-color: var(--color-bg-1);
+  border-radius: 10px;
+  box-shadow: 0 0 1px var(--color-border-4);
+}
+</style>

+ 17 - 3
src/views/Settings.vue

@@ -27,6 +27,13 @@
 
               {{ $t('settings.password') }}
             </a-menu-item>
+            <a-menu-item key="/settings/auth">
+              <template #icon>
+                <icon-lock class="icon" />
+              </template>
+
+              {{ $t('settings.authorization') }}
+            </a-menu-item>
 
             <!-- <a-menu-item key="/settings/phone">绑定电话号码</a-menu-item> -->
             <!-- <a-menu-item key="/settings/email">绑定邮箱</a-menu-item> -->
@@ -39,7 +46,13 @@
         <div class="settings-main-content-container">
           <div class="settings-aside-menu-title">
             <!-- {{ $t('settings.title') }} -->
-            {{ current_menu === 1 ? $t('settings.global') : $t('settings.password') }}
+            {{
+              current_menu === 1
+                ? $t('settings.global')
+                : current_menu === 2
+                ? $t('settings.password')
+                : $t('settings.authorization')
+            }}
           </div>
           <div :style="{ paddingTop: '20px' }">
             <router-view></router-view>
@@ -74,14 +87,15 @@ const content_style = {
 const collapsed = ref(false);
 const menu_map = {
   '/settings/global': 1,
-  '/settings/password': 2
+  '/settings/password': 2,
+  '/settings/auth': 3
 };
 
 const current_menu = ref('');
 
 const handleMenuClick = (key) => {
   current_menu.value = menu_map[key];
-  console.log(current_menu.value);
+  console.log(key);
   router.push({
     path: key
   });

+ 73 - 0
src/views/SettingsAuth.vue

@@ -0,0 +1,73 @@
+<template>
+  <div>
+    <a-form ref="ref_form" :model="form" :style="{ width: '600px' }" label-align="right">
+      <a-form-item label="版本类型">
+        <a-input v-model="form.version" disabled placeholder="Please enter something" />
+      </a-form-item>
+      <a-form-item label="激活状态">
+        <a-input v-model="form.status" disabled placeholder="Please enter something" />
+      </a-form-item>
+      <a-form-item label="请求码">
+        <a-input v-model="form.status" disabled placeholder="Please enter something" />
+      </a-form-item>
+      <a-form-item label="授权密钥">
+        <a-textarea
+          v-model="form.auth_key"
+          disabled
+          placeholder="Please enter something"
+          :auto-size="{
+            minRows: 2,
+            maxRows: 5
+          }"
+        />
+      </a-form-item>
+      <a-form-item label="到期时间">
+        <a-input v-model="form.end_time" disabled placeholder="Please enter something" />
+      </a-form-item>
+      <a-form-item>
+        <a-button type="primary" @click="toActive">激活</a-button>
+      </a-form-item>
+    </a-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, getCurrentInstance, computed } from 'vue';
+import { useRouter } from 'vue-router';
+
+import { Message } from '../3rd-libs/arco-vue-libs';
+
+const router = useRouter();
+
+const form = reactive({
+  version: '灵慧云智大模型平台-试用版',
+  status: '未激活',
+  request_code: 'ASASADFGHJKLGHFHJKL',
+  auth_key: 'ASASADFGHJKLGHFHJKLASASADFGHJKLGHFHJKL',
+  end_time: '2025-2-25 :12:00'
+});
+
+const loading = ref(false);
+
+const toActive = () => {
+  router.push({
+    path:'/auth'
+  })
+}
+</script>
+
+<style scoped>
+.setting-password-btn-container {
+  display: flex;
+  justify-content: flex-end;
+  flex-grow: 1;
+}
+:deep(.arco-input-wrapper .arco-input[disabled]) {
+  text-align: right;
+  color: #111;
+}
+:deep(.arco-textarea[disabled]) {
+  text-align: right;
+  color: #111;
+}
+</style>

+ 1 - 0
src/views/conversation/ConversationChatContainer.vue

@@ -697,6 +697,7 @@ const handleEditChat = (item) => {
   // edit_txt_value.value = marked(item.answer || '');
   edit_txt_value.value = item.answer;
   is_show_right_page.value = false;
+  show_mind_map.value = false;
   show_word_viewer.value = true;
 };
 

+ 2 - 2
src/views/conversation/ConversationChatWordViewer.vue

@@ -3,10 +3,10 @@
     <div class="word-viewer-header">
       <div class="word-viewer-header-btns">
         <a-button class="btn" @click="copyWord"
-          ><template #icon><icon-copy /></template>复制</a-button
+          ><template #icon><icon-copy /></template>{{ $t('conversation.copy') }}</a-button
         >
         <a-button class="btn" @click="download"
-          ><template #icon> <icon-download /> </template>下载</a-button
+          ><template #icon> <icon-download /> </template>{{ $t('conversation.download') }}</a-button
         >
         <a-button class="btn" @click="toClose"> <icon-close /></a-button>
       </div>