可信代码库-可信开源代码库AI助手首页开发完成
1097
package-lock.json
generated
@@ -19,6 +19,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@devui-design/icons": "^1.3.0",
|
"@devui-design/icons": "^1.3.0",
|
||||||
|
"@matechat/core": "^1.4.0",
|
||||||
"@micro-zoe/micro-app": "1.0.0-rc.3",
|
"@micro-zoe/micro-app": "1.0.0-rc.3",
|
||||||
"@sentry/vue": "^7.101.1",
|
"@sentry/vue": "^7.101.1",
|
||||||
"@types/crypto-js": "^4.1.1",
|
"@types/crypto-js": "^4.1.1",
|
||||||
@@ -45,8 +46,8 @@
|
|||||||
"vue": "^3.3.4",
|
"vue": "^3.3.4",
|
||||||
"vue-devui": "^1.6.31",
|
"vue-devui": "^1.6.31",
|
||||||
"vue-router": "^4.2.2",
|
"vue-router": "^4.2.2",
|
||||||
"yaml": "^2.4.1",
|
"xlsx": "^0.18.5",
|
||||||
"xlsx": "^0.18.5"
|
"yaml": "^2.4.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rushstack/eslint-patch": "^1.2.0",
|
"@rushstack/eslint-patch": "^1.2.0",
|
||||||
@@ -62,7 +63,6 @@
|
|||||||
"@vue/eslint-config-typescript": "^11.0.3",
|
"@vue/eslint-config-typescript": "^11.0.3",
|
||||||
"@vue/tsconfig": "^0.4.0",
|
"@vue/tsconfig": "^0.4.0",
|
||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
|
|
||||||
"eslint-plugin-vue": "^9.11.0",
|
"eslint-plugin-vue": "^9.11.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "^8.4.27",
|
"postcss": "^8.4.27",
|
||||||
|
|||||||
@@ -301,3 +301,22 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: rgb(246, 111, 106)
|
color: rgb(246, 111, 106)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.jyh-split {
|
||||||
|
background: #DFDFDF;
|
||||||
|
height: 20px;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jyh-button {
|
||||||
|
border-radius: 4px !important;
|
||||||
|
background: #E1E8FD !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jyh-button1 {
|
||||||
|
border-radius: 4px !important;
|
||||||
|
background: transparent !important;
|
||||||
|
color: black !important;
|
||||||
|
padding: 6px 6px !important;
|
||||||
|
}
|
||||||
|
|||||||
BIN
src/assets/imgs/jyh/ai/aiLogo1.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/assets/imgs/jyh/ai/aiLogo2.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
src/assets/imgs/jyh/ai/icon_api.png
Normal file
|
After Width: | Height: | Size: 456 B |
BIN
src/assets/imgs/jyh/ai/icon_bbx.png
Normal file
|
After Width: | Height: | Size: 311 B |
BIN
src/assets/imgs/jyh/ai/icon_cnxw.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/assets/imgs/jyh/ai/icon_dh.png
Normal file
|
After Width: | Height: | Size: 429 B |
BIN
src/assets/imgs/jyh/ai/icon_helper.png
Normal file
|
After Width: | Height: | Size: 421 B |
BIN
src/assets/imgs/jyh/ai/icon_hot.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/assets/imgs/jyh/ai/icon_jh.png
Normal file
|
After Width: | Height: | Size: 710 B |
BIN
src/assets/imgs/jyh/ai/icon_reflush.png
Normal file
|
After Width: | Height: | Size: 339 B |
BIN
src/assets/imgs/jyh/ai/icon_sj.png
Normal file
|
After Width: | Height: | Size: 412 B |
BIN
src/assets/imgs/jyh/ai/icon_yj.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/assets/imgs/jyh/ai/zh.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/imgs/jyh/ai/zh1.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
286
src/components/Header/AIHeader.vue
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
<template>
|
||||||
|
<div class="full-w" :style="{ height: `${height}px` }">
|
||||||
|
<div class="g-header fixed z-20" ref="headerRef" :class="{ 'home-background': isHome }">
|
||||||
|
<div class="g-toolbar w-full overflow-hidden" :class="[searchClass, route?.meta?.headerClassName]">
|
||||||
|
<div class="g-toolbar-left flex-shrink items-center">
|
||||||
|
<div class="flex-center gap-[16px]" v-if="!isHome">
|
||||||
|
<!-- <g-icon v-if="!asideSetShow" @click="$emit('clickMenu')" name="gt-hamburger" size="20px" class="cursor-pointer hover:!text-black" color="#1D1F3A"></g-icon>-->
|
||||||
|
<GLink class="g-toolbar-left-logo" @click="gotoAIHome" />
|
||||||
|
<GLink class="g-toolbar-left-title" @click="gotoAIHome">AI助手</GLink>
|
||||||
|
<div class="jyh-split"></div>
|
||||||
|
<d-button class="jyh-button" variant="solid" @click="handleLogin('login')">
|
||||||
|
<div class="flex flex-center">
|
||||||
|
<img style="height: 15px;margin-right: 8px" width="16" :src="icon_dh" />
|
||||||
|
<span>AI对话</span>
|
||||||
|
</div>
|
||||||
|
</d-button>
|
||||||
|
<d-button class="jyh-button1" variant="solid" @click="handleLogin('login')">
|
||||||
|
<div class="flex flex-center">
|
||||||
|
<img style="height: 15px;margin-right: 8px" width="16" :src="icon_bbx" />
|
||||||
|
<span>百宝箱</span>
|
||||||
|
</div>
|
||||||
|
</d-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="g-toolbar-right gap-[12px] flex-grow-0 flex-shrink-0">
|
||||||
|
<!--ai copilot-->
|
||||||
|
<a class="g-header-copilot" @click="gotoHome">
|
||||||
|
<img style="height: 15px;" width="16" :src="zh" />
|
||||||
|
<span class="ml-xs">返回平台搜索</span>
|
||||||
|
</a>
|
||||||
|
<d-button class="jyh-button1" variant="solid" @click="handleLogin('login')">
|
||||||
|
<div class="flex flex-center">
|
||||||
|
<img style="height: 15px;margin-right: 8px" width="16" :src="icon_sj" />
|
||||||
|
<span>升级产品</span>
|
||||||
|
</div>
|
||||||
|
</d-button>
|
||||||
|
<d-button class="jyh-button1" variant="solid" @click="handleLogin('login')">
|
||||||
|
<div class="flex flex-center">
|
||||||
|
<img style="height: 15px;margin-right: 8px" width="16" :src="icon_api" />
|
||||||
|
<span>API接口</span>
|
||||||
|
</div>
|
||||||
|
</d-button>
|
||||||
|
<d-button class="jyh-button1" variant="solid" @click="handleLogin('login')">
|
||||||
|
<div class="flex flex-center">
|
||||||
|
<img style="height: 15px;margin-right: 8px" width="16" :src="icon_helper" />
|
||||||
|
<span>帮助文档</span>
|
||||||
|
</div>
|
||||||
|
</d-button>
|
||||||
|
<UserAvatar />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="$slots.info || $slots.menu || $slots.bodyHeader" class="g-header-body">
|
||||||
|
<slot name="bodyHeader">
|
||||||
|
<div class="g-header-body-left h-full">
|
||||||
|
<slot name="info" />
|
||||||
|
</div>
|
||||||
|
<div class="g-header-body-right h-full">
|
||||||
|
<slot name="menu"></slot>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div v-if="$slots.headerBottom">
|
||||||
|
<slot name="headerBottom"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onBeforeUnmount, ref, watchEffect, computed } from 'vue';
|
||||||
|
import { useElementSize } from '@vueuse/core';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { useAccountStore } from '@/stores/user';
|
||||||
|
import { emitEvent } from '@/utils/eventBus';
|
||||||
|
|
||||||
|
import Create from './Create.vue';
|
||||||
|
import Entrance from './Entrance.vue';
|
||||||
|
import Notice from './Notice.vue';
|
||||||
|
import Search from './Search.vue';
|
||||||
|
import SearchAiHistory from './searchAiHistory.vue';
|
||||||
|
import UserAvatar from './UserAvatar.vue';
|
||||||
|
import { useWindowScroll } from '@vueuse/core';
|
||||||
|
import { usePageResize } from '@/utils/hooks/usePageResize';
|
||||||
|
import microApp from '@micro-zoe/micro-app';
|
||||||
|
import icon_dh from '@/assets/imgs/jyh/ai/icon_dh.png';
|
||||||
|
import icon_sj from '@/assets/imgs/jyh/ai/icon_sj.png';
|
||||||
|
import icon_api from '@/assets/imgs/jyh/ai/icon_api.png';
|
||||||
|
import icon_helper from '@/assets/imgs/jyh/ai/icon_helper.png';
|
||||||
|
import zh from '@/assets/imgs/jyh/ai/zh.png';
|
||||||
|
import icon_bbx from '@/assets/imgs/jyh/ai/icon_bbx.png';
|
||||||
|
|
||||||
|
const baseUrl = import.meta.env.VITE_BASE_URL;
|
||||||
|
const { y } = useWindowScroll();
|
||||||
|
const defaultLinkList = ref([]);
|
||||||
|
const route = useRoute();
|
||||||
|
const inSearch = ref(false);
|
||||||
|
const searchClass = computed(() => ({ 'border-b-transparent': inSearch.value && y.value === 0 }));
|
||||||
|
// header fixed布局高度自适应
|
||||||
|
const headerRef = ref(null);
|
||||||
|
const { height = 56 } = useElementSize(headerRef);
|
||||||
|
|
||||||
|
const userInfo = useAccountStore();
|
||||||
|
const { isLogin } = storeToRefs(userInfo);
|
||||||
|
const showSearch = computed(() => route.name !== 'home' && route.name !== 'search');
|
||||||
|
const isHome = computed(() => route.name === 'home');
|
||||||
|
const handleLogin = (type) => {
|
||||||
|
emitEvent('login', { type, triggerType: '主动注册' });
|
||||||
|
};
|
||||||
|
const { isMobile } = usePageResize();
|
||||||
|
const router = useRouter();
|
||||||
|
const gotoHome = (row) => {
|
||||||
|
// 后续请换成params,暂时params传参没传过去
|
||||||
|
router.push({ name: 'home' });
|
||||||
|
};
|
||||||
|
const gotoAIHome = (row) => {
|
||||||
|
// 后续请换成params,暂时params传参没传过去
|
||||||
|
router.push({ name: 'aihome' });
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* store 用户信息 */
|
||||||
|
/* @test 后面将清除 */
|
||||||
|
watchEffect(() => {});
|
||||||
|
microApp.router.beforeEach({
|
||||||
|
'micoro-app-homeweb-app': (to, from) => {
|
||||||
|
if (to.pathname === '/search') {
|
||||||
|
inSearch.value = true;
|
||||||
|
} else {
|
||||||
|
inSearch.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
defineExpose({
|
||||||
|
height
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import 'devui-theme/styles-var/devui-var.scss';
|
||||||
|
|
||||||
|
$radius: 4px;
|
||||||
|
$add-radius: 48px;
|
||||||
|
$header-bg: #fff;
|
||||||
|
|
||||||
|
.home-background {
|
||||||
|
background-color: #fff0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-header {
|
||||||
|
// overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: #FFFFFF0C;
|
||||||
|
:deep(.g-link) {
|
||||||
|
color: $devui-text-weak;
|
||||||
|
}
|
||||||
|
.g-header-copilot {
|
||||||
|
background: black;
|
||||||
|
color: #fff;
|
||||||
|
//width: 120px;
|
||||||
|
padding: 0 12px;
|
||||||
|
border-radius: 48px;
|
||||||
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
justify-content: center;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(41, 81, 224, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.g-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex: 1;
|
||||||
|
gap: 16px;
|
||||||
|
flex-basis: 56px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 24px;
|
||||||
|
border-bottom: 1px solid #f1f1f8;
|
||||||
|
:deep(.devui-button) {
|
||||||
|
padding: 6px 16px;
|
||||||
|
border-radius: $add-radius;
|
||||||
|
}
|
||||||
|
&-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 25px;
|
||||||
|
&-logo {
|
||||||
|
display: inline-block;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
background: url(../../assets/imgs/jyh/ai/aiLogo1.png) no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-position: 0 center;
|
||||||
|
}
|
||||||
|
&-title {
|
||||||
|
font-family: Inter;
|
||||||
|
font-weight: Semi Bold;
|
||||||
|
font-size: 20px;
|
||||||
|
line-height: 28px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: left;
|
||||||
|
background: linear-gradient(-81.02deg, #5EC9D4 0%, #83CA6F 24%, #D79808 49%, #F97C91 76%, #C87EDD 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
&-search {
|
||||||
|
max-width: 340px;
|
||||||
|
border-radius: $radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
@media screen and (max-width: 576px) {
|
||||||
|
@apply gap-[16px];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.border-b-transparent {
|
||||||
|
border-bottom-color: transparent !important;
|
||||||
|
}
|
||||||
|
&.border-b-show {
|
||||||
|
border-bottom-color: #f1f1f8 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.g-header-gray {
|
||||||
|
@apply bg-[#F9F9FB];
|
||||||
|
}
|
||||||
|
&-body {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 32px;
|
||||||
|
background-color: $header-bg;
|
||||||
|
border-bottom: 1px solid $devui-dividing-line;
|
||||||
|
flex-basis: 48px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1000px) {
|
||||||
|
.g-header {
|
||||||
|
.g-toolbar {
|
||||||
|
padding: 20px;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
.g-toolbar-left-logo {
|
||||||
|
width: 28px;
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
&-body {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn-add {
|
||||||
|
background-color: #000;
|
||||||
|
color: #fff !important;
|
||||||
|
width: 84px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
span {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 576px) {
|
||||||
|
.hidden-m {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.g-header-copilot {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<d-layout class="d-layout h-full" :class="{ 'home-background': isHome }">
|
<d-layout class="d-layout h-full" :class="{ 'home-background': isHome }">
|
||||||
<d-header class="d-header">
|
<d-header class="d-header">
|
||||||
<!-- header -->
|
<!-- header -->
|
||||||
<Header @clickMenu="handleClickMenu" :asideSetShow="asideSetShow" ref="refHeader">
|
<AIHeader @clickMenu="handleClickMenu" :asideSetShow="asideSetShow" ref="refHeader">
|
||||||
<!-- 二级导航左侧内容 -->
|
<!-- 二级导航左侧内容 -->
|
||||||
<template v-if="$slots.headerLeft && !route?.meta?.hideNav" #info>
|
<template v-if="$slots.headerLeft && !route?.meta?.hideNav" #info>
|
||||||
<slot name="headerLeft"></slot>
|
<slot name="headerLeft"></slot>
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
<template v-if="$slots.headerBottom && !route?.meta?.hideNav" #headerBottom>
|
<template v-if="$slots.headerBottom && !route?.meta?.hideNav" #headerBottom>
|
||||||
<slot name="headerBottom"></slot>
|
<slot name="headerBottom"></slot>
|
||||||
</template>
|
</template>
|
||||||
</Header>
|
</AIHeader>
|
||||||
</d-header>
|
</d-header>
|
||||||
<!-- 顶栏信息 -->
|
<!-- 顶栏信息 -->
|
||||||
<div v-if="$slots.contentBanner">
|
<div v-if="$slots.contentBanner">
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
defineOptions({ name: 'DefaultLayout' });
|
defineOptions({ name: 'DefaultLayout' });
|
||||||
import { RouterView, useRoute, useRouter } from 'vue-router';
|
import { RouterView, useRoute, useRouter } from 'vue-router';
|
||||||
import { computed, ref, watch, watchEffect, onMounted, onUnmounted } from 'vue';
|
import { computed, ref, watch, watchEffect, onMounted, onUnmounted } from 'vue';
|
||||||
import Header from '@/components/Header/index.vue';
|
import AIHeader from '@/components/Header/AIHeader.vue';
|
||||||
import Footer from '@/components/Footer/index.vue';
|
import Footer from '@/components/Footer/index.vue';
|
||||||
import Aside from './aside.vue';
|
import Aside from './aside.vue';
|
||||||
import { useGlobalInfoStore } from '@/stores/Global';
|
import { useGlobalInfoStore } from '@/stores/Global';
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import qs from 'qs';
|
|||||||
import * as Sentry from '@sentry/vue';
|
import * as Sentry from '@sentry/vue';
|
||||||
import { storageApis } from './api/storage-apis';
|
import { storageApis } from './api/storage-apis';
|
||||||
import { storageService } from './utils/apiStorage';
|
import { storageService } from './utils/apiStorage';
|
||||||
|
import MateChat from '@matechat/core';
|
||||||
|
|
||||||
import { gitCodeTheme } from './utils/theme/gitcodeTheme';
|
import { gitCodeTheme } from './utils/theme/gitcodeTheme';
|
||||||
const themeService = ThemeServiceInit({ 'gitcode-theme': gitCodeTheme }, 'gitcode-theme');
|
const themeService = ThemeServiceInit({ 'gitcode-theme': gitCodeTheme }, 'gitcode-theme');
|
||||||
@@ -184,6 +185,7 @@ Sentry.init({
|
|||||||
app.use(Icon);
|
app.use(Icon);
|
||||||
app.use(dInput);
|
app.use(dInput);
|
||||||
app.use(DevUI);
|
app.use(DevUI);
|
||||||
|
app.use(MateChat);
|
||||||
app.component('gc-checkbox-group', DCheckboxGroup);
|
app.component('gc-checkbox-group', DCheckboxGroup);
|
||||||
app.component('gc-checkbox', DCheckbox);
|
app.component('gc-checkbox', DCheckbox);
|
||||||
app.component('gc-option', Option);
|
app.component('gc-option', Option);
|
||||||
|
|||||||
@@ -117,12 +117,12 @@ export default [
|
|||||||
{
|
{
|
||||||
path: '/ai/home',
|
path: '/ai/home',
|
||||||
name: 'aihome',
|
name: 'aihome',
|
||||||
component: () => import('@/views/Jyh/Home/index.vue'),
|
component: () => import('@/views/Jyh/AI/Home/index.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
micorApp: ['micoro-app-homeweb-app'],
|
micorApp: ['micoro-app-homeweb-app'],
|
||||||
hasMobile: true,
|
hasMobile: true,
|
||||||
hiddenFooter: true,
|
hiddenFooter: true,
|
||||||
reportTitle: '首页',
|
reportTitle: 'AI首页',
|
||||||
className: 'w-full min-w-full',
|
className: 'w-full min-w-full',
|
||||||
headerClassName: '',
|
headerClassName: '',
|
||||||
asideMenu: 'drawer' // 左侧菜单抽屉模式
|
asideMenu: 'drawer' // 左侧菜单抽屉模式
|
||||||
|
|||||||
64
src/views/Jyh/AI/Home/AIinout.vue
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<McInput :value="inputValue" :loading="loading" @submit="onSubmit">
|
||||||
|
<template #head>
|
||||||
|
<div class="appendix-wrap">
|
||||||
|
<div class="appendix-item">
|
||||||
|
<span>README.md</span>
|
||||||
|
<i class="icon-code-editor-close"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #extra>
|
||||||
|
<div class="input-foot-left">
|
||||||
|
<span><i class="icon-at"></i>智能体</span>
|
||||||
|
<span><i class="icon-appendix"></i>附件</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</McInput>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { defineComponent, ref } from 'vue';
|
||||||
|
import { McInput } from '@matechat/core';
|
||||||
|
|
||||||
|
const inputValue = ref('');
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const onSubmit = (e) => {
|
||||||
|
loading.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false;
|
||||||
|
}, 1000);
|
||||||
|
console.log('input submit---', e);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.input-foot-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-text);
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.appendix-wrap {
|
||||||
|
display: flex;
|
||||||
|
padding: 4px 8px;
|
||||||
|
|
||||||
|
.appendix-item {
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: var(--devui-border-radius);
|
||||||
|
background-color: var(--devui-area);
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-left: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
103
src/views/Jyh/AI/Home/GuessYouWantToAsk.vue
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<template>
|
||||||
|
<div class="guess-you-want-to-ask-card">
|
||||||
|
<div class="card-title">
|
||||||
|
<img src="@/assets/imgs/jyh/ai/icon_cnxw.png" style="width: 20px;height: 20px;margin-right: 8px"></img>
|
||||||
|
<span>猜你想问</span>
|
||||||
|
<d-button @click="changeQuestions" class="jyh-button1" variant="solid">
|
||||||
|
<div class="flex flex-center">
|
||||||
|
<img style="height: 15px;margin-right: 8px" width="16" src="@/assets/imgs/jyh/ai/icon_reflush.png" />
|
||||||
|
<span>换一批</span>
|
||||||
|
</div>
|
||||||
|
</d-button>
|
||||||
|
</div>
|
||||||
|
<div class="card-description">
|
||||||
|
<button v-for="(question, index) in questions" :key="index" class="question-button">
|
||||||
|
{{ question }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
// 假设的图标 URL,你可以根据实际情况修改
|
||||||
|
const iconUrl = 'https://example.com/icon.png';
|
||||||
|
|
||||||
|
// 初始化问题列表
|
||||||
|
const questions = ref([
|
||||||
|
'列出热门开源软件',
|
||||||
|
'开源软件',
|
||||||
|
'未通过校验列表',
|
||||||
|
'通过校验列表',
|
||||||
|
'可使用、未治理和有风险的软件有哪些',
|
||||||
|
'危险和严重的个人预警通知',
|
||||||
|
'我的订阅列表'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 换一批问题的函数
|
||||||
|
const changeQuestions = () => {
|
||||||
|
// 这里可以实现从后端获取新问题列表的逻辑
|
||||||
|
// 示例中简单地更新问题列表
|
||||||
|
questions.value = [
|
||||||
|
'热门数据库软件有哪些',
|
||||||
|
'数据库软件的选型',
|
||||||
|
'代码漏洞检测方法',
|
||||||
|
'性能优化策略'
|
||||||
|
];
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.guess-you-want-to-ask-card {
|
||||||
|
border-radius: 24px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #191919;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title i {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-icon {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-description {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-button {
|
||||||
|
border: none;
|
||||||
|
border-radius: 35px;
|
||||||
|
background: #F3F3F3;
|
||||||
|
padding: 6px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-button:hover {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jyh-button1 {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
139
src/views/Jyh/AI/Home/SwiperComponent.vue
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div ref="mySwiper" class="swiper" id="swiper">
|
||||||
|
<!-- Slides -->
|
||||||
|
<div class="swiper-wrapper">
|
||||||
|
<div style="padding: 20px 6px" class="swiper-slide" v-for="item in slideData" :key="item.id">
|
||||||
|
<div class="ach-item bg-f" @click="onSelectItem(item)">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-title">
|
||||||
|
<img :src="item.icon" style="width: 20px;height: 20px;margin-right: 8px"></img>
|
||||||
|
<span >{{ item.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-description">{{ item.description }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Navigation buttons -->
|
||||||
|
<div class="swiper-button-prev"></div>
|
||||||
|
<div class="swiper-button-next"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import Swiper from 'swiper';
|
||||||
|
import { Navigation, Autoplay } from 'swiper/modules';
|
||||||
|
import 'swiper/css';
|
||||||
|
import 'swiper/css/navigation';
|
||||||
|
import icon_hot from '@/assets/imgs/jyh/ai/icon_hot.png';
|
||||||
|
import icon_yj from '@/assets/imgs/jyh/ai/icon_yj.png';
|
||||||
|
import icon_jh from '@/assets/imgs/jyh/ai/icon_jh.png';
|
||||||
|
|
||||||
|
const mySwiper = ref(null);
|
||||||
|
const slideData = [
|
||||||
|
{ id: 1, title: '热门开源软件', description: '列出热门开源软件',icon:icon_hot },
|
||||||
|
{ id: 2, title: '预警公告', description: '列出最近预警公告',icon:icon_yj },
|
||||||
|
{ id: 3, title: '你可以帮我做什么', description: '了解当前AI助手可以帮忙干什么',icon:icon_jh }
|
||||||
|
];
|
||||||
|
|
||||||
|
const onSelectItem = (item) => {
|
||||||
|
console.log('Selected item:', item);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
new Swiper(mySwiper.value, {
|
||||||
|
// Swiper选项
|
||||||
|
observer: true,
|
||||||
|
observeParents: true,
|
||||||
|
modules: [Navigation, Autoplay],
|
||||||
|
slidesPerView: 3,
|
||||||
|
spaceBetween: 20,
|
||||||
|
autoplay: {
|
||||||
|
delay: 2500,
|
||||||
|
disableOnInteraction: false
|
||||||
|
},
|
||||||
|
navigation: {
|
||||||
|
nextEl: '.swiper-button-next',
|
||||||
|
prevEl: '.swiper-button-prev'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.swiper {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-radius: 24px;
|
||||||
|
background: #FFFFFF;
|
||||||
|
padding: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #191919;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title i {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-description {
|
||||||
|
margin-left: 28px;
|
||||||
|
margin-top: 4px;
|
||||||
|
color: #595959;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: regular;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-prev {
|
||||||
|
left: -18px;
|
||||||
|
}
|
||||||
|
.swiper-button-next {
|
||||||
|
right: -18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-prev, .swiper-button-next {
|
||||||
|
top: 55%;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: inline-flex;
|
||||||
|
padding: 12px;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
border-radius: 100px;
|
||||||
|
border: 2px solid #FFF;
|
||||||
|
background: rgba(255, 255, 255, 0.50);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper-button-prev:after, .swiper-button-next:after {
|
||||||
|
color: #4E5969;
|
||||||
|
font-family: swiper-icons;
|
||||||
|
font-size: 16px;
|
||||||
|
text-transform: none !important;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-variant: initial;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
507
src/views/Jyh/AI/Home/index.vue
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
<template>
|
||||||
|
<div class="home-container">
|
||||||
|
<div class="home-content">
|
||||||
|
<div v-if="startChat" ref="conversationRef" class="conversation-area">
|
||||||
|
<template v-for="(msg, idx) in messages" :key="idx">
|
||||||
|
<McBubble v-if="msg.from === 'user'" :content="msg.content" :align="'right'" :avatarConfig="msg.avatarConfig"></McBubble>
|
||||||
|
<McBubble v-else :loading="msg.loading ?? false" :avatarConfig="msg.avatarConfig">
|
||||||
|
<McMarkdownCard :content="msg.content" :theme="theme"></McMarkdownCard>
|
||||||
|
<template #bottom>
|
||||||
|
<div class="bubble-bottom-operations">
|
||||||
|
<i class="icon-copy-new"></i>
|
||||||
|
<i class="icon-like"></i>
|
||||||
|
<i class="icon-dislike"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</McBubble>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div v-else class="welcome-page">
|
||||||
|
<div class="home-title">
|
||||||
|
<img src="@/assets/imgs/jyh/ai/aiLogo2.png" alt="logo" />
|
||||||
|
<h1>可信开源代码库AI助手</h1>
|
||||||
|
</div>
|
||||||
|
<div class="home-detail">
|
||||||
|
<div class="home-detail-1">Hi,欢迎使用可信开源代码库AI助手</div>
|
||||||
|
<div class="home-detail-2">可信开源代码库AI助手 可以辅助研发人员进行软件查询、批量校验、查看软件详情等。</div>
|
||||||
|
<div class="home-detail-2">作为AI模型,可信开源代码库AI助手 提供的答案可能不总是确定或准确的,但您的反馈可以帮助 可信开源代码库AI助手 做得更好。</div>
|
||||||
|
</div>
|
||||||
|
<div style="width: 100%;margin-top: -20px">
|
||||||
|
<SwiperComponent />
|
||||||
|
</div>
|
||||||
|
<!--猜你想问-->
|
||||||
|
<div style="width: 100%;margin-top: -20px">
|
||||||
|
<GuessYouWantToAsk />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!--操作按钮-->
|
||||||
|
<div class="new-convo-button">
|
||||||
|
<McPrompt
|
||||||
|
v-if="startChat"
|
||||||
|
class="simple-prompt"
|
||||||
|
style="flex: 1"
|
||||||
|
:list="simplePrompt"
|
||||||
|
:direction="'horizontal'"
|
||||||
|
@itemClick="onItemClick($event)"
|
||||||
|
></McPrompt>
|
||||||
|
<div v-else class="agent-knowledge">
|
||||||
|
<d-dropdown :position="['top']" @toggle="(val) => (isAgentOpen = val)">
|
||||||
|
<div class="agent-wrapper">
|
||||||
|
<img src="@/assets/imgs/jyh/ai/aiLogo2.png" />
|
||||||
|
<span>{{ selectedAgent.label }}</span>
|
||||||
|
<i class="icon-infrastructure"></i>
|
||||||
|
<i :class="['icon-chevron-down-2', { 'is-open': isAgentOpen }]"></i>
|
||||||
|
</div>
|
||||||
|
<template #menu>
|
||||||
|
<McList :data="agentList" @select="(val) => (selectedAgent = val)"></McList>
|
||||||
|
</template>
|
||||||
|
</d-dropdown>
|
||||||
|
<span class="agent-knowledge-dividing-line"></span>
|
||||||
|
<div class="knowledge-wrapper">
|
||||||
|
<i class="icon-operation-log"></i>
|
||||||
|
<span>添加知识</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<d-button icon="add" shape="circle" title="新建对话" size="sm" @click="onNewConvo" />
|
||||||
|
</div>
|
||||||
|
<!--输入框-->
|
||||||
|
<div style="padding: 0 12px 12px 12px;width: 100%">
|
||||||
|
<McInput :placeholder="placeholder" :value="inputValue" :maxLength="maxLength" @change="(e) => (inputValue = e)" @submit="onSubmit">
|
||||||
|
<template #extra>
|
||||||
|
<div class="input-foot-wrapper">
|
||||||
|
<div class="input-foot-left">
|
||||||
|
<span v-for="(item, index) in inputFootIcons" :key="index" @click="() => onInputIconClick(item)">
|
||||||
|
<i :class="item.icon"></i>
|
||||||
|
{{ item.text }}
|
||||||
|
</span>
|
||||||
|
<span class="input-foot-dividing-line"></span>
|
||||||
|
<span class="input-foot-maxlength">{{ inputValue.length }}/{{maxLength}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="input-foot-right">
|
||||||
|
<d-button icon="op-clearup" shape="round" :disabled="!inputValue" @click="inputValue = ''">清空输入</d-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</McInput>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 添加使用条款部分 -->
|
||||||
|
<div class="usage-terms">
|
||||||
|
<p>内容由AI生成,无法确保准确性和完整性,仅供参考:使用条款 隐私声明</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, defineComponent, nextTick, onMounted } from 'vue';
|
||||||
|
import { introPrompt, simplePrompt, mockAnswer, guessQuestions } from './mock.constants';
|
||||||
|
import SwiperComponent from './SwiperComponent.vue';
|
||||||
|
import GuessYouWantToAsk from './GuessYouWantToAsk.vue';
|
||||||
|
|
||||||
|
const inputValue = ref('');
|
||||||
|
const startChat = ref(false);
|
||||||
|
const conversationRef = ref();
|
||||||
|
const isAgentOpen = ref(false);
|
||||||
|
const theme = ref('light');
|
||||||
|
const maxLength = ref(8000);
|
||||||
|
const placeholder = ref('请输入问题描述,描述越详细 DevMate 回复越准确( Enter发送,Shift+Enter 换行,↑ 查看最近发出的消息 )');
|
||||||
|
let themeService;
|
||||||
|
const agentList = ref([
|
||||||
|
{ label: 'MateChat', value: 'matechat', active: true },
|
||||||
|
{ label: 'InsCode', value: 'inscode' },
|
||||||
|
]);
|
||||||
|
const selectedAgent = ref(agentList.value[0]);
|
||||||
|
const aiModelAvatar = {
|
||||||
|
imgSrc: 'https://matechat.gitcode.com/logo.svg',
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
};
|
||||||
|
const customerAvatar = {
|
||||||
|
imgSrc: 'https://matechat.gitcode.com/png/demo/userAvatar.svg',
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
};
|
||||||
|
const inputFootIcons = [
|
||||||
|
{ icon: 'icon-at', text: '智能体' },
|
||||||
|
{ icon: 'icon-standard', text: '词库' },
|
||||||
|
{ icon: 'icon-add', text: '附件' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const messages = ref([]);
|
||||||
|
|
||||||
|
const onInputIconClick = (e) => {
|
||||||
|
if (e.icon === 'icon-at') {
|
||||||
|
inputValue.value += `@${selectedAgent.value.label}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (e, answer = undefined) => {
|
||||||
|
if(e === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inputValue.value = '';
|
||||||
|
if (!messages.value.length) {
|
||||||
|
startChat.value = true;
|
||||||
|
}
|
||||||
|
messages.value.push({
|
||||||
|
from: 'user',
|
||||||
|
content: e,
|
||||||
|
avatarPosition: 'side-right',
|
||||||
|
avatarConfig: { ...customerAvatar },
|
||||||
|
});
|
||||||
|
nextTick(() => {
|
||||||
|
conversationRef.value?.scrollTo({
|
||||||
|
top: conversationRef.value.scrollHeight,
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
getAIAnswer(answer ?? e);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAIAnswer = (content) => {
|
||||||
|
messages.value.push({
|
||||||
|
from: 'ai-model',
|
||||||
|
content: '',
|
||||||
|
avatarPosition: 'side-left',
|
||||||
|
avatarConfig: { ...aiModelAvatar },
|
||||||
|
loading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 模拟流式数据返回 */
|
||||||
|
setTimeout(async () => {
|
||||||
|
messages.value.at(-1).loading = false;
|
||||||
|
for (let i = 0; i < content.length;) {
|
||||||
|
await new Promise(r => setTimeout(r, 300 * Math.random()));
|
||||||
|
messages.value[messages.value.length - 1].content = content.slice(0, i += Math.random() * 10);
|
||||||
|
nextTick(() => {
|
||||||
|
conversationRef.value?.scrollTo({
|
||||||
|
top: conversationRef.value.scrollHeight
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onNewConvo = () => {
|
||||||
|
startChat.value = false;
|
||||||
|
messages.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const onItemClick = (item) => {
|
||||||
|
if (mockAnswer[item.value]) {
|
||||||
|
// 使用 mock 数据
|
||||||
|
onSubmit(item.label, mockAnswer[item.value]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const themeChange = () => {
|
||||||
|
if (themeService) {
|
||||||
|
theme.value = themeService.currentTheme.id === 'infinity-theme' ? 'light' : 'dark';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if(typeof window !== 'undefined'){
|
||||||
|
themeService = window['devuiThemeService'];
|
||||||
|
}
|
||||||
|
themeChange();
|
||||||
|
if (themeService && themeService.eventBus) {
|
||||||
|
themeService.eventBus.add('themeChanged', themeChange);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.home-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.home-content {
|
||||||
|
font-size: 14px;
|
||||||
|
padding-top: 3%;
|
||||||
|
padding-bottom: 1%;
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-self: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.home-title {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
h1 {
|
||||||
|
color: #191919;
|
||||||
|
font-family: Huawei Sans;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36px;
|
||||||
|
line-height: 48px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 86px;
|
||||||
|
//filter: brightness(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-detail {
|
||||||
|
.home-detail-1 {
|
||||||
|
color: #191919;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: medium;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 32px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
.home-detail-2 {
|
||||||
|
color: #777777;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: regular;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-area,
|
||||||
|
.welcome-page {
|
||||||
|
height: 90%;
|
||||||
|
width: 100%;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
//overflow: auto;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-area {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-page {
|
||||||
|
gap: 24px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guess-question {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 12px;
|
||||||
|
border-radius: var(--devui-border-radius-card);
|
||||||
|
background-color: var(--devui-gray-form-control-bg);
|
||||||
|
|
||||||
|
.guess-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--devui-text);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
& > div:first-child {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
}
|
||||||
|
& > div:last-child {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
span {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guess-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
span {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-text);
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: var(--devui-border-radius-full);
|
||||||
|
background-color: var(--devui-gray-form-control-hover-bg);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble-bottom-operations {
|
||||||
|
margin-top: 8px;
|
||||||
|
i {
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--devui-icon-hover-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-convo-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
height: 39px;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.simple-prompt .mc-list) {
|
||||||
|
justify-content: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.intro-prompt .mc-list) {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operations {
|
||||||
|
i {
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--devui-global-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-knowledge {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.agent-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: var(--devui-border-radius-full);
|
||||||
|
background-color: var(--devui-area);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
color: var(--devui-text);
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
color: var(--devui-text);
|
||||||
|
transition: transform 0.3s ease-in-out;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-open {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-knowledge-dividing-line {
|
||||||
|
width: 1px;
|
||||||
|
height: 14px;
|
||||||
|
margin: 0 12px;
|
||||||
|
background-color: var(--devui-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.knowledge-wrapper {
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
color: var(--devui-text);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
|
.input-foot-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-text);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-dividing-line {
|
||||||
|
width: 1px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: var(--devui-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-maxlength {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-aide-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-right {
|
||||||
|
& > *:not(:first-child) {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.mc-input) {
|
||||||
|
background: #ffffff;
|
||||||
|
.mc-textarea {
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.usage-terms {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
color: #AEAEAE;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: regular;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
422
src/views/Jyh/AI/Home/index2.vue
Normal file
@@ -0,0 +1,422 @@
|
|||||||
|
<template>
|
||||||
|
<div class="demo-test">
|
||||||
|
<McHeader :logoImg="'@/assets/imgs/jyh/ai/aiLogo2.png'" :title="'MateChat'">
|
||||||
|
<template #operationArea>
|
||||||
|
<div class="operations">
|
||||||
|
<i class="icon-helping"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</McHeader>
|
||||||
|
<div v-if="startChat" ref="conversationRef" class="conversation-area">
|
||||||
|
<template v-for="(msg, idx) in messages" :key="idx">
|
||||||
|
<McBubble v-if="msg.from === 'user'" :content="msg.content" :align="'right'" :avatarConfig="msg.avatarConfig"></McBubble>
|
||||||
|
<McBubble v-else :loading="msg.loading ?? false" :avatarConfig="msg.avatarConfig">
|
||||||
|
<McMarkdownCard :content="msg.content" :theme="theme"></McMarkdownCard>
|
||||||
|
<template #bottom>
|
||||||
|
<div class="bubble-bottom-operations">
|
||||||
|
<i class="icon-copy-new"></i>
|
||||||
|
<i class="icon-like"></i>
|
||||||
|
<i class="icon-dislike"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</McBubble>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div v-else class="welcome-page">
|
||||||
|
<McIntroduction
|
||||||
|
logo-img="/logo2x.svg"
|
||||||
|
title="MateChat"
|
||||||
|
sub-title="Hi,欢迎使用 MateChat"
|
||||||
|
:description="[
|
||||||
|
'MateChat 可以辅助研发人员编码、查询知识和相关作业信息、编写文档等。',
|
||||||
|
'作为AI模型,MateChat 提供的答案可能不总是确定或准确的,但您的反馈可以帮助 MateChat 做的更好。',
|
||||||
|
]"
|
||||||
|
></McIntroduction>
|
||||||
|
<McPrompt :list="introPrompt.list" :direction="'horizontal'" class="intro-prompt" @itemClick="onItemClick($event)"></McPrompt>
|
||||||
|
<div class="guess-question">
|
||||||
|
<div class="guess-title">
|
||||||
|
<div>猜你想问</div>
|
||||||
|
<div>
|
||||||
|
<i class="icon-recover"></i>
|
||||||
|
<span>换一批</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="guess-content">
|
||||||
|
<span v-for="(item, index) in guessQuestions" :key="index" @click="onItemClick(item)">{{ item.label }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="new-convo-button">
|
||||||
|
<McPrompt
|
||||||
|
v-if="startChat"
|
||||||
|
class="simple-prompt"
|
||||||
|
style="flex: 1"
|
||||||
|
:list="simplePrompt"
|
||||||
|
:direction="'horizontal'"
|
||||||
|
@itemClick="onItemClick($event)"
|
||||||
|
></McPrompt>
|
||||||
|
<div v-else class="agent-knowledge">
|
||||||
|
<d-dropdown :position="['top']" @toggle="(val) => (isAgentOpen = val)">
|
||||||
|
<div class="agent-wrapper">
|
||||||
|
<img src="@/assets/imgs/jyh/ai/aiLogo2.png" />
|
||||||
|
<span>{{ selectedAgent.label }}</span>
|
||||||
|
<i class="icon-infrastructure"></i>
|
||||||
|
<i :class="['icon-chevron-down-2', { 'is-open': isAgentOpen }]"></i>
|
||||||
|
</div>
|
||||||
|
<template #menu>
|
||||||
|
<McList :data="agentList" @select="(val) => (selectedAgent = val)"></McList>
|
||||||
|
</template>
|
||||||
|
</d-dropdown>
|
||||||
|
<span class="agent-knowledge-dividing-line"></span>
|
||||||
|
<div class="knowledge-wrapper">
|
||||||
|
<i class="icon-operation-log"></i>
|
||||||
|
<span>添加知识</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<d-button icon="add" shape="circle" title="新建对话" size="sm" @click="onNewConvo" />
|
||||||
|
</div>
|
||||||
|
<div style="padding: 0 12px 12px 12px">
|
||||||
|
<McInput :value="inputValue" :maxLength="2000" @change="(e) => (inputValue = e)" @submit="onSubmit">
|
||||||
|
<template #extra>
|
||||||
|
<div class="input-foot-wrapper">
|
||||||
|
<div class="input-foot-left">
|
||||||
|
<span v-for="(item, index) in inputFootIcons" :key="index" @click="() => onInputIconClick(item)">
|
||||||
|
<i :class="item.icon"></i>
|
||||||
|
{{ item.text }}
|
||||||
|
</span>
|
||||||
|
<span class="input-foot-dividing-line"></span>
|
||||||
|
<span class="input-foot-maxlength">{{ inputValue.length }}/2000</span>
|
||||||
|
</div>
|
||||||
|
<div class="input-foot-right">
|
||||||
|
<d-button icon="op-clearup" shape="round" :disabled="!inputValue" @click="inputValue = ''">清空输入</d-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</McInput>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, defineComponent, nextTick, onMounted } from 'vue';
|
||||||
|
import { introPrompt, simplePrompt, mockAnswer, guessQuestions } from './mock.constants';
|
||||||
|
|
||||||
|
const inputValue = ref('');
|
||||||
|
const startChat = ref(false);
|
||||||
|
const conversationRef = ref();
|
||||||
|
const isAgentOpen = ref(false);
|
||||||
|
const theme = ref('light');
|
||||||
|
let themeService;
|
||||||
|
const agentList = ref([
|
||||||
|
{ label: 'MateChat', value: 'matechat', active: true },
|
||||||
|
{ label: 'InsCode', value: 'inscode' },
|
||||||
|
]);
|
||||||
|
const selectedAgent = ref(agentList.value[0]);
|
||||||
|
const aiModelAvatar = {
|
||||||
|
imgSrc: 'https://matechat.gitcode.com/logo.svg',
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
};
|
||||||
|
const customerAvatar = {
|
||||||
|
imgSrc: 'https://matechat.gitcode.com/png/demo/userAvatar.svg',
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
};
|
||||||
|
const inputFootIcons = [
|
||||||
|
{ icon: 'icon-at', text: '智能体' },
|
||||||
|
{ icon: 'icon-standard', text: '词库' },
|
||||||
|
{ icon: 'icon-add', text: '附件' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const messages = ref([]);
|
||||||
|
|
||||||
|
const onInputIconClick = (e) => {
|
||||||
|
if (e.icon === 'icon-at') {
|
||||||
|
inputValue.value += `@${selectedAgent.value.label}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = (e, answer = undefined) => {
|
||||||
|
if(e === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
inputValue.value = '';
|
||||||
|
if (!messages.value.length) {
|
||||||
|
startChat.value = true;
|
||||||
|
}
|
||||||
|
messages.value.push({
|
||||||
|
from: 'user',
|
||||||
|
content: e,
|
||||||
|
avatarPosition: 'side-right',
|
||||||
|
avatarConfig: { ...customerAvatar },
|
||||||
|
});
|
||||||
|
nextTick(() => {
|
||||||
|
conversationRef.value?.scrollTo({
|
||||||
|
top: conversationRef.value.scrollHeight,
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
getAIAnswer(answer ?? e);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAIAnswer = (content) => {
|
||||||
|
messages.value.push({
|
||||||
|
from: 'ai-model',
|
||||||
|
content: '',
|
||||||
|
avatarPosition: 'side-left',
|
||||||
|
avatarConfig: { ...aiModelAvatar },
|
||||||
|
loading: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 模拟流式数据返回 */
|
||||||
|
setTimeout(async () => {
|
||||||
|
messages.value.at(-1).loading = false;
|
||||||
|
for (let i = 0; i < content.length;) {
|
||||||
|
await new Promise(r => setTimeout(r, 300 * Math.random()));
|
||||||
|
messages.value[messages.value.length - 1].content = content.slice(0, i += Math.random() * 10);
|
||||||
|
nextTick(() => {
|
||||||
|
conversationRef.value?.scrollTo({
|
||||||
|
top: conversationRef.value.scrollHeight
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onNewConvo = () => {
|
||||||
|
startChat.value = false;
|
||||||
|
messages.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const onItemClick = (item) => {
|
||||||
|
if (mockAnswer[item.value]) {
|
||||||
|
// 使用 mock 数据
|
||||||
|
onSubmit(item.label, mockAnswer[item.value]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const themeChange = () => {
|
||||||
|
if (themeService) {
|
||||||
|
theme.value = themeService.currentTheme.id === 'infinity-theme' ? 'light' : 'dark';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if(typeof window !== 'undefined'){
|
||||||
|
themeService = window['devuiThemeService'];
|
||||||
|
}
|
||||||
|
themeChange();
|
||||||
|
if (themeService && themeService.eventBus) {
|
||||||
|
themeService.eventBus.add('themeChanged', themeChange);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.demo-test {
|
||||||
|
width: 100%;
|
||||||
|
min-width: 500px;
|
||||||
|
height: calc(100vh - 180px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.conversation-area,
|
||||||
|
.welcome-page {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conversation-area {
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-page {
|
||||||
|
gap: 24px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guess-question {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px 12px;
|
||||||
|
border-radius: var(--devui-border-radius-card);
|
||||||
|
background-color: var(--devui-gray-form-control-bg);
|
||||||
|
|
||||||
|
.guess-title {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: var(--devui-text);
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
& > div:first-child {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
}
|
||||||
|
& > div:last-child {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
cursor: pointer;
|
||||||
|
span {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guess-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
span {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-text);
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: var(--devui-border-radius-full);
|
||||||
|
background-color: var(--devui-gray-form-control-hover-bg);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bubble-bottom-operations {
|
||||||
|
margin-top: 8px;
|
||||||
|
i {
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--devui-icon-hover-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-convo-button {
|
||||||
|
padding: 0 12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
height: 39px;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.simple-prompt .mc-list) {
|
||||||
|
justify-content: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.intro-prompt .mc-list) {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operations {
|
||||||
|
i {
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--devui-global-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-knowledge {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.agent-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: var(--devui-border-radius-full);
|
||||||
|
background-color: var(--devui-area);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
color: var(--devui-text);
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
color: var(--devui-text);
|
||||||
|
transition: transform 0.3s ease-in-out;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-open {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-knowledge-dividing-line {
|
||||||
|
width: 1px;
|
||||||
|
height: 14px;
|
||||||
|
margin: 0 12px;
|
||||||
|
background-color: var(--devui-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.knowledge-wrapper {
|
||||||
|
font-size: var(--devui-font-size);
|
||||||
|
color: var(--devui-text);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
span {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-wrapper {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
|
.input-foot-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-text);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-dividing-line {
|
||||||
|
width: 1px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: var(--devui-line);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-maxlength {
|
||||||
|
font-size: var(--devui-font-size-sm);
|
||||||
|
color: var(--devui-aide-text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-foot-right {
|
||||||
|
& > *:not(:first-child) {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
473
src/views/Jyh/AI/Home/indexOld.vue
Normal file
@@ -0,0 +1,473 @@
|
|||||||
|
<template>
|
||||||
|
<div class="home-container">
|
||||||
|
<div class="home-content">
|
||||||
|
<div class="home-title">
|
||||||
|
<img src="@/assets/imgs/jyh/ai/aiLogo2.png" alt="logo" />
|
||||||
|
<h1>可信开源代码库AI助手</h1>
|
||||||
|
</div>
|
||||||
|
<div class="home-detail">
|
||||||
|
<div class="home-detail-1">Hi,欢迎使用可信开源代码库AI助手</div>
|
||||||
|
<div class="home-detail-2">可信开源代码库AI助手 可以辅助研发人员进行软件查询、批量校验、查看软件详情等。</div>
|
||||||
|
<div class="home-detail-2">作为AI模型,可信开源代码库AI助手 提供的答案可能不总是确定或准确的,但您的反馈可以帮助 可信开源代码库AI助手 做得更好。</div>
|
||||||
|
</div>
|
||||||
|
<!--swiper-->
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<SwiperComponent />
|
||||||
|
</div>
|
||||||
|
<!--猜你想问-->
|
||||||
|
<div style="width: 100%;margin-top: -20px">
|
||||||
|
<GuessYouWantToAsk />
|
||||||
|
</div>
|
||||||
|
<!--AI大模型输入框-->
|
||||||
|
<div style="width: 100%;">
|
||||||
|
<AIinout />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<d-modal class="warning-modal" v-model="warningModalVisable" title="" style="width: 600px">
|
||||||
|
<EarlyWarningDetail :warningData="currentWarning" :type="'user'"></EarlyWarningDetail>
|
||||||
|
</d-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, onBeforeUnmount, computed } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { useAccount } from '@/utils/hooks/useAccount';
|
||||||
|
import AdvanceSearch from '@/components/AdvanceSearch/index.vue';
|
||||||
|
import { getHomeNoticeList } from '@/api/jyh';
|
||||||
|
import EarlyWarningDetail from '@/views/Jyh/PersonalCenter/Detail/EarlyWarningDetail.vue';
|
||||||
|
import { useGlobalInfoStore } from '@/stores/Global';
|
||||||
|
const { updateHeaderSearch } = useGlobalInfoStore();
|
||||||
|
const { accountInfo } = useAccount();
|
||||||
|
import { useDiscussGetUserInfo } from '@/api/discussion/hook';
|
||||||
|
import SwiperComponent from './SwiperComponent.vue';
|
||||||
|
import GuessYouWantToAsk from './GuessYouWantToAsk.vue';
|
||||||
|
import AIinout from './AIinout.vue';
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
const inputGlow = ref(false);
|
||||||
|
const searchStr = ref('');
|
||||||
|
const position = ref(['right-start', 'right-end']);
|
||||||
|
const industryOptions = ref(['通信', '军工', '金融', '能源']);
|
||||||
|
const searchType = ref('软件');
|
||||||
|
const searchOptions = ref(['软件']);
|
||||||
|
const offset = ref({ mainAxis: 7, crossAxis: -10 });
|
||||||
|
const isKeepOpen = ref(true);
|
||||||
|
const isOpen = ref(false);
|
||||||
|
const cateRotate = ref(0);
|
||||||
|
const infoList = ref([]);
|
||||||
|
const warningModalVisable = ref(false);
|
||||||
|
const currentWarning = ref();
|
||||||
|
|
||||||
|
const { isLogin } = useDiscussGetUserInfo();
|
||||||
|
const homeSearch = ref(null);
|
||||||
|
const dropdownWidth = ref(0);
|
||||||
|
const tagMap = {
|
||||||
|
critical: {
|
||||||
|
text: '致命',
|
||||||
|
color: '#c7000b'
|
||||||
|
},
|
||||||
|
high: {
|
||||||
|
text: '高',
|
||||||
|
color: '#f66f6a'
|
||||||
|
},
|
||||||
|
medium: {
|
||||||
|
text: '中',
|
||||||
|
color: '#fac20a'
|
||||||
|
},
|
||||||
|
low: {
|
||||||
|
text: '低',
|
||||||
|
color: '#5e7ce0'
|
||||||
|
},
|
||||||
|
Critical: {
|
||||||
|
text: '致命',
|
||||||
|
color: '#c7000b'
|
||||||
|
},
|
||||||
|
High: {
|
||||||
|
text: '高',
|
||||||
|
color: '#f66f6a'
|
||||||
|
},
|
||||||
|
Medium: {
|
||||||
|
text: '中',
|
||||||
|
color: '#fac20a'
|
||||||
|
},
|
||||||
|
Low: {
|
||||||
|
text: '低',
|
||||||
|
color: '#5e7ce0'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const rotate = computed(() => {
|
||||||
|
return isOpen.value ? 180 : 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchInput = ref(null);
|
||||||
|
const openAdvancedSearch = () => {
|
||||||
|
isOpen.value = !isOpen.value;
|
||||||
|
inputGlow.value = isOpen.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
const check = () => {
|
||||||
|
router.push({
|
||||||
|
name: 'Search',
|
||||||
|
query: { tab: 'BatchVerify' } // 通过查询参数指定 Tab
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const closeOutside = () => {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = (formData) => {
|
||||||
|
isOpen.value = false;
|
||||||
|
router.push({
|
||||||
|
name: 'Search',
|
||||||
|
query: {
|
||||||
|
softwareName: searchStr.value ? searchStr.value : '',
|
||||||
|
searchType: getIndustryValue(searchType.value),
|
||||||
|
softwareVersion: formData.softwareVersion || '',
|
||||||
|
programmingLanguage: formData.programmingLanguage || '',
|
||||||
|
interestTag: formData.interestTag || '',
|
||||||
|
industry: formData.industry || '',
|
||||||
|
licenseName: formData.licenseName || '',
|
||||||
|
dependentSoftware: formData.dependentSoftware || '',
|
||||||
|
releaseDateStart: formData.dateRange && formData.dateRange.length > 0 ? formData.dateRange[0] : '',
|
||||||
|
releaseDateEnd: formData.dateRange && formData.dateRange.length > 0 ? formData.dateRange[1] : ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const inputFocus = () => {
|
||||||
|
inputGlow.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const inputBlur = () => {
|
||||||
|
inputGlow.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateDropdownWidth = () => {
|
||||||
|
if (homeSearch.value) {
|
||||||
|
dropdownWidth.value = homeSearch.value.offsetWidth * 0.85;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const globalInfo = useGlobalInfoStore();
|
||||||
|
const industryList = globalInfo.industryList;
|
||||||
|
const getIndustryValue = (name) => {
|
||||||
|
const industry = industryList.find((item) => item.name === name);
|
||||||
|
return industry ? industry.value : ''; // 如果找不到,返回默认值
|
||||||
|
};
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
// updateHeaderSearch({ searchWord: searchStr.value, searchType: selectedCate.value });
|
||||||
|
router.push({
|
||||||
|
name: 'Search',
|
||||||
|
query: {
|
||||||
|
softwareName: searchStr.value ? searchStr.value : '',
|
||||||
|
searchType: getIndustryValue(searchType.value)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// window.open(`${import.meta.env.VITE_BASE_URL}repoList?softwareName=${searchStr.value ? searchStr.value : ''}&searchType=${getIndustryValue(searchType.value)}`, '_blank')
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCategoryChange = (event) => {
|
||||||
|
searchType.value = event?.name || '软件';
|
||||||
|
globalInfo.updateHeaderSearch({ softwareName: softwareName.value, searchType: event.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const onCateToggle = (event) => {
|
||||||
|
cateRotate.value = event ? 180 : 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkMore = () => {
|
||||||
|
router.push({ name: 'PersonalCenter' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const openWarningDetail = (event, index) => {
|
||||||
|
infoList.value.forEach((item, i) => {
|
||||||
|
if (i <= index) {
|
||||||
|
item.dotColor = 'var(--devui-info)';
|
||||||
|
} else {
|
||||||
|
item.dotColor = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
warningModalVisable.value = true;
|
||||||
|
currentWarning.value = event;
|
||||||
|
};
|
||||||
|
|
||||||
|
let resizeObserver: ResizeObserver | null = null;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
resizeObserver = new ResizeObserver(updateDropdownWidth);
|
||||||
|
if (homeSearch.value) {
|
||||||
|
resizeObserver.observe(homeSearch.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDropdownWidth();
|
||||||
|
|
||||||
|
document.querySelector('body').onclick = (e) => {
|
||||||
|
const className = e.target.className;
|
||||||
|
if (
|
||||||
|
!className.includes('close-isopen') &&
|
||||||
|
!className.includes('devui-badge__content') &&
|
||||||
|
!className.includes('advanced-search')
|
||||||
|
) {
|
||||||
|
isOpen.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (resizeObserver && homeSearch.value) {
|
||||||
|
resizeObserver.unobserve(homeSearch.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const getNoticeList = async () => {
|
||||||
|
const res: any = await getHomeNoticeList();
|
||||||
|
if (!res.error) {
|
||||||
|
infoList.value = res.data.data || [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getNoticeList();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import 'devui-theme/styles-var/devui-var.scss';
|
||||||
|
|
||||||
|
.home-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.home-content {
|
||||||
|
font-size: 14px;
|
||||||
|
height: 80%;
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-self: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.home-title {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
h1 {
|
||||||
|
color: #191919;
|
||||||
|
font-family: Huawei Sans;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 48px;
|
||||||
|
line-height: 48px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 90px;
|
||||||
|
//filter: brightness(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-search {
|
||||||
|
width: 574px;
|
||||||
|
height: 46px;
|
||||||
|
border: 1px solid #dfe1e5;
|
||||||
|
box-shadow: 0px 2px 8px 0px rgba(60, 64, 67, 0.25);
|
||||||
|
border-radius: 24px;
|
||||||
|
|
||||||
|
//width: 100%;
|
||||||
|
//height: 40px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background-color: white;
|
||||||
|
//border-radius: 10px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px;
|
||||||
|
//box-shadow: var(--devui-shadow, 0 2px 12px 0);
|
||||||
|
input {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-search {
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 1px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: var(--devui-form-control-line, #d7d8da);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-search-menu {
|
||||||
|
height: 300px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-operation {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.batch-btn {
|
||||||
|
color: $devui-aide-text;
|
||||||
|
width: 150px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-color: $devui-aide-text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-information {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
//overflow: auto;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
img {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.sub-title {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.devui-timeline-item-data-left) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.devui-timeline-item-dot) {
|
||||||
|
scale: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-search {
|
||||||
|
:deep(.devui-input-slot__prepend),
|
||||||
|
:deep(.devui-input-slot__append),
|
||||||
|
:deep(.devui-input__wrapper) {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.devui-select__selection--glow-style),
|
||||||
|
:deep(.devui-input--glow-style) {
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.glow-border {
|
||||||
|
border: 1px solid var(--devui-form-control-line, #d7d8da);
|
||||||
|
border-color: var(--devui-form-control-line-active, #5e7ce0) !important;
|
||||||
|
box-shadow: 0 0 0 4px var(--devui-form-control-interactive-outline, rgba(94, 124, 224, 0.08));
|
||||||
|
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--devui-list-item-hover-bg, #f2f5fc);
|
||||||
|
color: var(--devui-list-item-hover-text, #526ecc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-menu {
|
||||||
|
padding: 8px;
|
||||||
|
margin: 0;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 8px;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
width: 140px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.devui-timeline-item-data-right) {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-detail {
|
||||||
|
.home-detail-1 {
|
||||||
|
color: #191919;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: medium;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 32px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
.home-detail-2 {
|
||||||
|
color: #777777;
|
||||||
|
font-family: HarmonyOS Sans SC;
|
||||||
|
font-weight: regular;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
letter-spacing: 0px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
57
src/views/Jyh/AI/Home/mock.constants.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// mock.constants.js
|
||||||
|
|
||||||
|
export const introPrompt = {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
label: '如何使用 MateChat 辅助编码?',
|
||||||
|
value: 'how_to_use_for_coding',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'MateChat 能查询哪些知识?',
|
||||||
|
value: 'what_knowledge_can_query',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '如何添加知识到 MateChat?',
|
||||||
|
value: 'how_to_add_knowledge',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const simplePrompt = [
|
||||||
|
{
|
||||||
|
label: '快速查询代码示例',
|
||||||
|
value: 'quick_code_example',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '获取性能优化建议',
|
||||||
|
value: 'performance_optimization',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '辅助编写文档',
|
||||||
|
value: 'write_document_assistance',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const mockAnswer = {
|
||||||
|
how_to_use_for_coding: 'MateChat 可以通过输入相关的代码需求,比如函数实现、算法逻辑等,它会为您提供代码示例和解释。您可以输入具体的代码功能描述,例如“编写一个冒泡排序算法”,MateChat 会给出相应的代码实现。',
|
||||||
|
what_knowledge_can_query: 'MateChat 可以查询编程知识、算法、数据结构、编程语言特性、框架使用方法等。还可以查询作业相关的信息,例如任务进度、资源分配等。',
|
||||||
|
how_to_add_knowledge: '要添加知识到 MateChat,您可以点击界面上的“添加知识”按钮,然后按照提示上传相关的文档或者输入具体的知识内容即可。',
|
||||||
|
quick_code_example: '以下是一个简单的 JavaScript 代码示例,用于计算数组的总和:\n```javascript\nconst arr = [1, 2, 3, 4, 5];\nconst sum = arr.reduce((acc, val) => acc + val, 0);\nconsole.log(sum);\n```',
|
||||||
|
performance_optimization: '性能优化可以从多个方面入手,例如减少循环嵌套、合理使用缓存、优化算法复杂度等。对于具体的代码,您可以提供给 MateChat 进行分析和建议。',
|
||||||
|
write_document_assistance: 'MateChat 可以辅助您编写文档,例如生成文档大纲、填充内容等。您可以输入文档的主题和一些关键信息,然后让 MateChat 帮助您生成相关内容。',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const guessQuestions = [
|
||||||
|
{
|
||||||
|
label: 'MateChat 支持哪些编程语言?',
|
||||||
|
value: 'supported_programming_languages',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '如何查看 MateChat 的使用记录?',
|
||||||
|
value: 'how_to_view_usage_record',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'MateChat 能处理复杂的业务逻辑吗?',
|
||||||
|
value: 'handle_complex_business_logic',
|
||||||
|
},
|
||||||
|
];
|
||||||