From 33d303e7a4a701391544a006b17e4966591cd7f2 Mon Sep 17 00:00:00 2001
From: "1960116313@qq.com" <1960116313@qq.com>
Date: Thu, 18 Jan 2024 13:38:44 +0800
Subject: [PATCH] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E8=A7=92=E8=89=B2?=
 =?UTF-8?q?=E5=BA=94=E7=94=A8=E9=A1=B5=E9=9D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/api/base/role.ts                     |  14 ++
 src/api/base/user.ts                     |   0
 src/components/AppRoleDefault/index.d.ts |  20 ++
 src/components/AppRoleDefault/index.ts   |   3 +
 src/components/AppRoleDefault/index.vue  | 293 +++++++++++++++++++++++
 src/layout/AppMenu/index.vue             |   2 +-
 src/router/index.ts                      |   8 +
 src/utils/axios/index.ts                 |   3 +-
 src/views/login/index.vue                |  25 +-
 src/views/role/index.vue                 |  46 ++++
 10 files changed, 401 insertions(+), 13 deletions(-)
 create mode 100644 src/api/base/role.ts
 delete mode 100644 src/api/base/user.ts
 create mode 100644 src/components/AppRoleDefault/index.d.ts
 create mode 100644 src/components/AppRoleDefault/index.ts
 create mode 100644 src/components/AppRoleDefault/index.vue
 create mode 100644 src/views/role/index.vue

diff --git a/src/api/base/role.ts b/src/api/base/role.ts
new file mode 100644
index 0000000..dc49961
--- /dev/null
+++ b/src/api/base/role.ts
@@ -0,0 +1,14 @@
+import { defHttp } from '@/utils/axios/index'
+
+// 角色
+export async function getRole(type: number) {
+  return defHttp.get({
+    url: `/open-chat/roleInfo/list?type=${type}`,
+  })
+}
+// 应用
+export function getAppList() {
+  return defHttp.get({
+    url: `/open-chat/roleInfo/app/group/list`,
+  })
+}
diff --git a/src/api/base/user.ts b/src/api/base/user.ts
deleted file mode 100644
index e69de29..0000000
diff --git a/src/components/AppRoleDefault/index.d.ts b/src/components/AppRoleDefault/index.d.ts
new file mode 100644
index 0000000..a2f03c2
--- /dev/null
+++ b/src/components/AppRoleDefault/index.d.ts
@@ -0,0 +1,20 @@
+export interface RoleData {
+  roleImg: string
+  roleName: string
+  roleInfo: string
+  remark: string
+}
+
+interface RoleInfoAppModel {
+  id: number
+  roleName: string
+  roleType: string
+  roleInfo: string
+  roleImg: string
+  type: number
+}
+
+export interface AppGroup {
+  groupName: string
+  roleInfoAppModelList: RoleInfoAppModel[]
+}
diff --git a/src/components/AppRoleDefault/index.ts b/src/components/AppRoleDefault/index.ts
new file mode 100644
index 0000000..6184f60
--- /dev/null
+++ b/src/components/AppRoleDefault/index.ts
@@ -0,0 +1,3 @@
+import AppRoleDefault from './index.vue'
+
+export { AppRoleDefault }
diff --git a/src/components/AppRoleDefault/index.vue b/src/components/AppRoleDefault/index.vue
new file mode 100644
index 0000000..5cb4dfb
--- /dev/null
+++ b/src/components/AppRoleDefault/index.vue
@@ -0,0 +1,293 @@
+<!-- 子菜单容器组件 -->
+<script setup lang="ts">
+import { ref } from 'vue'
+import type { AppGroup, RoleData } from './index.d'
+import { getAppList, getRole } from '@/api/base/role'
+
+const roleList = ref<RoleData[]>([])
+const application = ref<AppGroup[]>([])
+const typeIndex = ref(0)
+
+// 角色
+function getRoleData() {
+  getRole(1).then((res) => {
+    roleList.value = res
+  })
+}
+// 应用
+function getAppData() {
+  getAppList().then((res) => {
+    application.value = res
+  })
+}
+getRoleData()
+getAppData()
+
+// 应用切换
+function handleChange(index: number) {
+  typeIndex.value = index
+}
+</script>
+
+<template>
+  <div class="app-role-default-box w-full h-full">
+    <div class="applicationsbox">
+      <div class="rolecounseling">
+        <div class="title">
+          角色咨询
+        </div>
+        <div class="role-box">
+          <div
+            v-for="(item, index) in roleList"
+            :key="index"
+            class="role-card"
+          >
+            <div class="top">
+              <div class="avatar">
+                <img :src="item.roleImg" class="roleImg" />
+              </div>
+              <div class="exchange">
+                交流
+              </div>
+            </div>
+            <div class="message">
+              <div class="role">
+                <div class="rolename">
+                  {{ item.roleName }}
+                </div>
+                <div class="name">
+                  {{ item.roleInfo }}
+                </div>
+              </div>
+              <div class="explain">
+                {{ item.remark }}
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="applicationbox">
+        <div class="title">
+          应用市场
+        </div>
+        <div class="type">
+          <div>
+            <div
+              v-for="(item, index) in application"
+              :key="index"
+              :class="typeIndex === index ? 'typename change' : 'typename'"
+              @click="handleChange(index)"
+            >
+              {{ item.groupName }}
+            </div>
+          </div>
+          <div v-if="application.length > 0" class="list-box">
+            <div
+              v-for="(item, index) in application[typeIndex].roleInfoAppModelList"
+              :key="index"
+              class="applyList"
+            >
+              <div class="img">
+                <img class="apple-img" :src="item.roleImg" />
+                <div class="name">
+                  {{ item.roleName }}
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+@include app('role-default-box') {
+  .applicationsbox {
+    width: 100%;
+    .rolecounseling {
+      width: 100%;
+      max-height: 60vh;
+      overflow: auto;
+      .title {
+        font-size: 16px;
+        font-family:
+          PingFangSC,
+          PingFang SC;
+        font-weight: 600;
+        color: #141515;
+      }
+      .role-box {
+        margin-top: 15px;
+        display: flex;
+        flex-wrap: wrap;
+        column-gap: 2%;
+        margin-top: 40px;
+
+        .role-card {
+          width: 23%;
+          height: 100px;
+          margin-bottom: 35px;
+          background: linear-gradient(169deg, #edf3ff 0%, #f7f9ff 100%);
+          box-shadow: 1px 4px 10px 0px rgba(194, 205, 235, 0.49);
+          border-radius: 10px;
+
+          cursor: pointer;
+
+          .top {
+            display: flex;
+            position: relative;
+            .avatar {
+              margin-top: -20px;
+              padding-left: 25px;
+              font-size: 0;
+              .roleImg {
+                width: 55px;
+                height: 55px;
+              }
+            }
+            .exchange {
+              position: absolute;
+              top: 5px;
+              right: 0px;
+              width: 4px;
+              height: 30px;
+              background: linear-gradient(131deg, #226aff 0%, #3fc6ff 100%);
+              font-size: 0;
+              border-radius: 100px 0px 0px 100px;
+              transition: width 0.3s linear 0s;
+            }
+          }
+          .message {
+            width: 80%;
+            margin: 10px auto 0;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+
+            .role {
+              display: flex;
+              align-items: center;
+              .rolename {
+                font-size: 15px;
+                font-family:
+                  PingFangSC,
+                  PingFang SC;
+                font-weight: 600;
+                color: #253351;
+              }
+              .name {
+                margin-left: 30px;
+                font-size: 13px;
+                font-family:
+                  PingFangSC,
+                  PingFang SC;
+                font-weight: 400;
+                color: #253351;
+              }
+            }
+            .explain {
+              font-size: 11px;
+              font-family:
+                PingFangSC,
+                PingFang SC;
+              font-weight: 400;
+              color: #335d91;
+              line-height: 25px;
+              white-space: nowrap;
+              overflow: hidden;
+              text-overflow: ellipsis;
+            }
+          }
+          &:hover .exchange {
+            width: 50px;
+            background: linear-gradient(131deg, #226aff 0%, #3fc6ff 100%);
+            border-radius: 100px 0px 0px 100px;
+            text-align: center;
+            color: white;
+            line-height: 30px;
+            font-size: 14px;
+            font-family:
+              PingFangSC,
+              PingFang SC;
+            font-weight: 500;
+          }
+        }
+      }
+    }
+
+    .applicationbox {
+      width: 100%;
+      padding: 20px 0px;
+      max-height: 50vh;
+      .title {
+        font-size: 16px;
+        font-family:
+          PingFangSC,
+          PingFang SC;
+        font-weight: 600;
+        color: #141515;
+      }
+      .type {
+        display: flex;
+        flex-direction: column;
+        margin-top: 20px;
+        overflow: auto;
+        .typename {
+          cursor: pointer;
+          border-radius: 16px;
+          margin: 0 11px;
+          padding: 4px 8px;
+          font-size: 13px;
+          font-family:
+            PingFangSC,
+            PingFang SC;
+          font-weight: 500;
+          display: inline-block;
+
+          &.change {
+            background: #236cff;
+            color: #ffffff;
+          }
+        }
+
+        .list-box {
+          margin-top: 20px;
+          display: flex;
+          flex-wrap: wrap;
+
+          .applyList {
+            display: flex;
+            flex-direction: column;
+            padding: 10px 15px;
+            .img {
+              position: relative;
+              overflow: hidden;
+              cursor: pointer;
+              .apple-img {
+                width: 100px;
+                height: 100px;
+              }
+              .name {
+                width: 100%;
+                position: absolute;
+                bottom: 0px;
+                left: 0;
+                text-align: center;
+                color: white;
+                font-size: 11px;
+
+                height: 25px;
+                border-bottom-left-radius: 5px;
+                border-bottom-right-radius: 5px;
+                line-height: 25px;
+                background-color: rgba(0, 0, 0, 0.5);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>
diff --git a/src/layout/AppMenu/index.vue b/src/layout/AppMenu/index.vue
index 583babc..00223ef 100644
--- a/src/layout/AppMenu/index.vue
+++ b/src/layout/AppMenu/index.vue
@@ -23,7 +23,7 @@ const menu = ref<MenuItem[]>([
   {
     name: '角色',
     icon: 'jue_se',
-    path: '',
+    path: '/role',
     key: MenuTypeEnum.ROLE,
   },
   {
diff --git a/src/router/index.ts b/src/router/index.ts
index 30277ca..2e77db7 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -47,6 +47,14 @@ export const constantRoutes: Array<RouteRecordRaw> = [
           title: '文生图',
         },
       },
+      {
+        name: 'Role',
+        path: '/Role',
+        component: () => import('@/views/role/index.vue'),
+        meta: {
+          title: '角色',
+        },
+      },
     ],
   },
 
diff --git a/src/utils/axios/index.ts b/src/utils/axios/index.ts
index 4e7f04b..68bcc67 100644
--- a/src/utils/axios/index.ts
+++ b/src/utils/axios/index.ts
@@ -258,7 +258,8 @@ function createAxios(opt?: Partial<CreateAxiosOptions>) {
       {
         // See https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes
         // authentication schemes,e.g: Bearer
-        tokenScheme: 'crypto',
+        // crypto
+        tokenScheme: '',
         authenticationScheme: 'Basic',
         timeout: 10 * 1000,
         // 基础接口地址
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index a6fad9d..8290183 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -122,10 +122,10 @@ function timer() {
             欢迎使用
           </div>
           <div class="zh">
-            青鸟AI助手-同聪
+            青鸟语言大模型-同聪
           </div>
           <div class="en">
-            Bluebird AI Assistant - Tong Cong
+            THE BIG LANGUAGE MODEL BLUEBIRO - Tong Cong
           </div>
         </div>
       </div>
@@ -139,7 +139,7 @@ function timer() {
           :wrapper-col="{ span: 22 }"
           autocomplete="off"
         >
-          <div class="login_title">
+          <div class="login-title">
             登录/注册
           </div>
           <FormItem
@@ -150,7 +150,6 @@ function timer() {
                 <img
                   class="icon"
                   :src="Yh"
-                  style="width: 20px;"
                 />
               </template>
             </Input>
@@ -163,7 +162,6 @@ function timer() {
                 <img
                   class="icon"
                   :src="Yzm"
-                  style="width: 20px;"
                 />
               </template>
               <template #suffix>
@@ -235,7 +233,7 @@ function timer() {
         top: 20%;
         left: 10%;
         .welcome {
-          font-size: 55px;
+          font-size: 50px;
           font-family: PingFang-SC, PingFang-SC;
           font-weight: 300;
           color: #ffffff;
@@ -243,7 +241,7 @@ function timer() {
           letter-spacing: 4px;
         }
         .zh {
-          font-size: 30px;
+          font-size: 26px;
           padding-top: 20px;
           font-family: PingFang-SC, PingFang-SC;
           font-weight: 400;
@@ -251,7 +249,7 @@ function timer() {
           letter-spacing: 5px;
         }
         .en {
-          font-size: 16px;
+          font-size: 13px;
           font-family: PingFang-SC, PingFang-SC;
           font-weight: 400;
           color: #77a4ff;
@@ -274,8 +272,12 @@ function timer() {
       top: 0;
       right: 2%;
       .login-Form {
-        width: 75%;
+        width: 70%;
         margin: 0 auto;
+        .icon {
+          width: 15px;
+          height: 15px;
+        }
         .time {
           font-size: 12px;
           color: #48a1fe;
@@ -287,7 +289,7 @@ function timer() {
           color: #333;
           border-bottom: 1px solid #c8cbd6;
           &::placeholder {
-            font-size: 12px;
+            font-size: 10px;
             color: #6e7382;
             letter-spacing: 3px;
           }
@@ -296,7 +298,8 @@ function timer() {
           }
         }
 
-        .login_title {
+        .login-title {
+          margin-top: 50px;
           margin-bottom: 30px;
           color: #505458;
           font-size: 19px;
diff --git a/src/views/role/index.vue b/src/views/role/index.vue
new file mode 100644
index 0000000..b19692c
--- /dev/null
+++ b/src/views/role/index.vue
@@ -0,0 +1,46 @@
+<script setup lang="ts">
+import { ref } from 'vue'
+
+import { AppContainerBox } from '@/components/AppContainerBox'
+import { AppSubMenuTitle } from '@/components/AppSubMenuTitle'
+import { AppSubMenuList } from '@/components/AppSubMenuList'
+import { AppRoleDefault } from '@/components/AppRoleDefault'
+import type { SubMenuItem } from '@/components/AppSubMenuList/index.d'
+
+const subMenuActive = ref(0)
+const subMenuList = ref<SubMenuItem[]>([
+  {
+    title: '新对话1',
+    content: '这是一个新的对话哦;啦啦啦',
+    id: '1',
+  },
+  {
+    title: '新对话2',
+    content: '这是一个新的对话哦',
+    id: '2',
+  },
+])
+
+function handleSubMenuChange(index: number) {
+  subMenuActive.value = index
+}
+</script>
+
+<template>
+  <AppContainerBox>
+    <template #subMenu>
+      <AppSubMenuTitle title="角色会话"></AppSubMenuTitle>
+      <!-- <div class="px-5 mb-5">
+        <Button type="primary" class="w-full">
+          新建会话
+        </Button>
+      </div> -->
+      <AppSubMenuList :list="subMenuList" :active-index="subMenuActive" @change="handleSubMenuChange"></AppSubMenuList>
+    </template>
+    <template #content>
+      <AppRoleDefault></AppRoleDefault>
+    </template>
+  </AppContainerBox>
+</template>
+
+<style scoped></style>