wujingjing
2024-10-28 d2efaa204e1217b90b5f99581e5a68802867f20e
group_type
已修改9个文件
254 ■■■■■ 文件已修改
customer_list/common/static/fonts/ywiconfont/iconfont.css 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
customer_list/common/static/fonts/ywiconfont/iconfont.ttf 补丁 | 查看 | 原始文档 | blame | 历史
customer_list/common/static/fonts/ywiconfont/iconfont.woff 补丁 | 查看 | 原始文档 | blame | 历史
customer_list/common/static/fonts/ywiconfont/iconfont.woff2 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/Chat.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/components/playBar/PlayBar.vue 92 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/stores/chatRoom.ts 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/ch/home/component/waterRight/top.vue 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
customer_list/common/static/fonts/ywiconfont/iconfont.css
@@ -1,8 +1,8 @@
@font-face {
  font-family: "ywifont"; /* Project id 4655417 */
  src: url('iconfont.woff2?t=1729665723269') format('woff2'),
       url('iconfont.woff?t=1729665723269') format('woff'),
       url('iconfont.ttf?t=1729665723269') format('truetype');
  src: url('iconfont.woff2?t=1730084434771') format('woff2'),
       url('iconfont.woff?t=1730084434771') format('woff'),
       url('iconfont.ttf?t=1730084434771') format('truetype');
}
.ywifont {
@@ -13,6 +13,30 @@
  -moz-osx-font-smoothing: grayscale;
}
.ywicon-bangong:before {
  content: "\e683";
}
.ywicon-yewu:before {
  content: "\e8a0";
}
.ywicon-quanxian:before {
  content: "\e60c";
}
.ywicon-mima:before {
  content: "\e608";
}
.ywicon-shezhi:before {
  content: "\e7eb";
}
.ywicon-xitongtongzhi1:before {
  content: "\e647";
}
.ywicon-bingzhuangtu:before {
  content: "\e70e";
}
customer_list/common/static/fonts/ywiconfont/iconfont.ttf
Binary files differ
customer_list/common/static/fonts/ywiconfont/iconfont.woff
Binary files differ
customer_list/common/static/fonts/ywiconfont/iconfont.woff2
Binary files differ
src/components/chat/Chat.vue
@@ -1,7 +1,7 @@
<template>
    <div class="flex h-full">
        <div class="flex flex-col h-full flex-auto">
            <div ref="chatListDom" class="relative h-full flex flex-col items-center overflow-y-auto">
            <div ref="chatListDom" class="relative h-full flex flex-col items-center overflow-y-auto ">
                <span
                    class="more-loading absolute text-blue-400 left-[50%] translate-x-[-50%] cursor-pointer w-10"
                    v-loading="moreIsLoading"
@@ -127,7 +127,7 @@
                            </div>
                        </div>
                    </div>
                    <div v-if="showAskMore" class="ml-4 mt-5 text-sm">
                    <div v-if="showAskMore" class="ml-4 mt-5 text-sm pb-10">
                        <div class="text-gray-600 mb-5">你可以继续问我:</div>
                        <div class="space-y-2 inline-flex flex-col">
                            <div
@@ -143,7 +143,7 @@
                </div>
            </div>
            <div class="sticky bottom-0 w-full p-6 pb-8 bg-[rgb(247,248,250)] flex justify-center">
            <div class="sticky bottom-0 w-full p-6   bg-[rgb(247,248,250)] flex justify-center">
                <PlayBar
                    v-model:voicePageIsShow="voicePageIsShow"
                    :isTalking="isTalking"
@@ -175,7 +175,7 @@
import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue';
import CustomDrawer from '/@/components/drawer/CustomDrawer.vue';
import router from '/@/router';
import { activeChatRoom, activeLLMId, activeSampleId, activeSectionAId, getRoomConfig, roomConfig } from '/@/stores/chatRoom';
import { activeChatRoom, activeGroupType, activeLLMId, activeRoomId, activeSampleId, activeSectionAId, getRoomConfig, roomConfig } from '/@/stores/chatRoom';
import { ErrorCode } from '/@/utils/request';
const chatWidth = '75%';
@@ -187,6 +187,7 @@
});
const currentRoute = router.currentRoute;
const currentRouteId = currentRoute.value.query.id as string;
activeRoomId.value = currentRouteId;
const chatListDom = ref<HTMLDivElement>();
const messageList = ref<ChatMessage[]>([]);
const computedMessageList = computed(() => {
@@ -294,12 +295,16 @@
        process_id: processId.value,
        question: text,
        // FIXME: 暂时这样
        section_a_id: currentSectionAId,
        // section_a_id: currentSectionAId,
        history_group_id: currentRouteId,
        raw_mode: roomConfig.value?.[currentRouteId]?.isAnswerByLLM ?? false,
        ...judgeParams,
    } as any;
    if(activeGroupType.value){
        params.group_type = activeGroupType.value;
    }
    if (currentSampleId) {
        params.sample_id = currentSampleId;
        currentSampleId = '';
src/components/chat/components/playBar/PlayBar.vue
@@ -1,5 +1,35 @@
<template>
    <div class="playInput hl_input">
    <div class="playInput hl_input rounded-b-[22px] input-border input-shadow" :class="{ 'rounded-t-[22px]': !currentGroupTypeIsShow }">
        <!-- 应用场景 -->
        <div v-if="!currentGroupTypeIsShow" class="application-scenarios absolute bottom-[114%] left-4">
            <div class="flex-items-center space-x-2">
                <div
                    class="border border-gray-400 border-solid h-8 flex-items-center px-3 py-2 rounded-2xl cursor-pointer space-x-1 hover:bg-[#c5e0ff] hover:text-[#1c86ff]"
                    v-for="item in groupTypeList"
                    @click="groupTypeClick(item)"
                >
                    <span :class="['ywifont', groupTypeMapIcon[item]]"></span>
                    <div class="">{{ item }}</div>
                </div>
            </div>
        </div>
        <!-- 当前应用场景 -->
        <div
            v-else
            class="bg-[#f9fafb] rounded-t-[22px] absolute bottom-[100%] left-0 w-full input-border h-11 flex-items-center justify-between text-[14px]"
            style="padding: 4px 4px 4px 18px; border-bottom: none"
        >
            <div class="flex-items-center">
                <span :class="[groupTypeMapIcon[activeGroupType]]" class="ywifont mr-2 !text-[14px]"></span>
                <div>{{ activeGroupType }}</div>
            </div>
            <el-tooltip content="退出应用场景" placement="top">
                <span
                    @click="closeCurrentGroupType"
                    class="ywifont ywicon-guanbi mr-3 rounded-sm p-1 hover:bg-[#eaebec] cursor-pointer"
                ></span>
            </el-tooltip>
        </div>
        <div class="assembly flex">
            <el-button title="插件菜单" class="label flex items-center cursor-pointer" link>
                <img src="/static/images/wave/PlugIn.png" class="set-icon box-border" />
@@ -9,7 +39,6 @@
        <div class="set-input">
            <!-- @input="inputText" -->
            <el-input
                ref="inputRef"
                class="relative align-bottom set-inputAnswer"
@@ -41,11 +70,7 @@
                        <span class="text-sm text-gray-500 pr-1.5">{{ index + 1 }}</span>
                        <template v-if="sentenceSplitMap?.[item.question]">
                            <template v-for="part in sentenceSplitMap[item.question]">
                                <span
                                    v-if="part.isKeyword"
                                    class="text-blue-400 font-bold cursor-pointer"
                                    >{{ part.partStr }}</span
                                >
                                <span v-if="part.isKeyword" class="text-blue-400 font-bold cursor-pointer">{{ part.partStr }}</span>
                                <span v-else>{{ part.partStr }}</span>
                            </template>
                        </template>
@@ -57,11 +82,11 @@
            <div class="upload_img space-y">
                <div class="imgbox cursor-pointer flex items-center">
                    <!-- <el-button title="AI看图" class="cursor-pointer" link style="margin-left: unset">
                        <img src="/static/images/wave/LookImg.png" class="set-img-icon box-border" />
                    </el-button> -->
                <img src="/static/images/wave/LookImg.png" class="set-img-icon box-border" />
            </el-button> -->
                    <!-- <el-button title="AI语音对话" class="cursor-pointer" link style="margin-left: unset" @click="audioChangeWord">
                        <img src="/static/images/wave/HeadImg.png" class="set-img-icon box-border" />
                    </el-button> -->
                <img src="/static/images/wave/HeadImg.png" class="set-img-icon box-border" />
            </el-button> -->
                    <el-button title="发送" :disabled="isTalking" class="cursor-pointer" link @click="emits('sendClick')">
                        <div class="send">
@@ -85,13 +110,14 @@
import type { InputInstance } from 'element-plus';
import { ElMessage } from 'element-plus';
import getCaretCoordinates from 'textarea-caret';
import { computed, nextTick, ref } from 'vue';
import { computed, nextTick, ref, triggerRef } from 'vue';
import InfoDetail from './InfoDetail.vue';
import VoicePage from './voicePage/VoicePage.vue';
import { getMetricsNames, querySimilarityHistory } from '/@/api/ai/chat';
import { onClickOutside } from '@vueuse/core';
import _ from 'lodash';
import { activeGroupType, groupTypeList, groupTypeMapIcon } from '/@/stores/chatRoom';
const emits = defineEmits(['sendClick']);
const props = defineProps(['isTalking', 'isHome']);
const voicePageIsShow = defineModel('voicePageIsShow', {
@@ -217,7 +243,7 @@
 */
const getSentenceMatchMap = (sentences: string[], keywords: any[]) => {
    if (!sentences || sentences.length === 0) return null;
    if (!keywords || keywords.length===0) {
    if (!keywords || keywords.length === 0) {
        return sentences.map((item) => ({
            partStr: item,
            startIndex: 0,
@@ -375,6 +401,21 @@
    infoDetailIsShow.value = true;
};
//#endregion
//#region ====================== 当前应用场景 ======================
const currentGroupTypeIsShow = computed(() => !!activeGroupType.value);
const groupTypeClick = (item) => {
    activeGroupType.value = item;
    inputRef.value.focus();
};
// 关闭当前 groupType 面板
const closeCurrentGroupType = () => {
    activeGroupType.value = null;
};
//#endregion
</script>
<style scoped lang="scss">
.set-waterTitle {
@@ -426,6 +467,21 @@
    border-color: #1c86ff;
    color: #fff;
}
.input-shadow {
    -webkit-box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3;
    box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3;
}
.input-border {
    border: 1px solid #00000030;
    -webkit-transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    -o-transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
}
.playInput {
    align-items: flex-start;
    width: 760px;
@@ -438,15 +494,7 @@
    align-items: flex-end;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    border-radius: 22px;
    border: 1px solid #00000030;
    -webkit-box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3;
    box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3;
    -webkit-transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    -o-transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    background-color: #fff;
    .assembly {
        position: relative;
src/main.ts
@@ -12,6 +12,7 @@
import { initBackEndControlRoutes } from './router/backEnd';
import '/@/theme/index.scss';
import '@amap/amap-jsapi-types';
import { getAllData } from './stores/chatRoom';
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
@@ -24,3 +25,6 @@
    await initBackEndControlRoutes();
    app.use(pinia).use(router).use(ElementPlus).use(i18n).use(VueGridLayout).mount('#app');
})();
// 获取全局数据
getAllData();
src/stores/chatRoom.ts
@@ -1,17 +1,24 @@
import { computed, ref } from 'vue';
import type { ChatRoomItem } from '../layout/component/sidebar/components/types';
import { getSectionList } from '../api/ai/chat';
/**
 * Room 关联的一些配置
 */
export type RoomConfig = {
    /** 是否直接调用大模型(通义千问)回答 */
    isAnswerByLLM: boolean;
    /** @description 从首页进去获取的第一个回复,回调函数 */
    firstResCb: any;
    /** @description 当前聊天室的 group_type */
    activeGroupType: string;
};
export type RoomConfigKey = keyof RoomConfig;
export const roomConfig = ref<Record<string, RoomConfig>>(null);
export const setRoomConfig = <T extends RoomConfigKey>(roomId: string, key: T, value: RoomConfig[T]) => {
    if (!roomId) return;
    if (!roomConfig.value) {
        roomConfig.value = {};
    }
@@ -25,6 +32,7 @@
};
export const getRoomConfig = <T extends RoomConfigKey>(roomId: string, key: T) => {
    if (!roomId) return;
    if (!roomConfig.value) {
        return null;
    }
@@ -43,9 +51,39 @@
export const activeSectionAId = ref(null);
export const activeLLMId = ref(null);
/** @description 当前聊天室 groupType */
export const activeGroupType = computed({
    get: () => {
        const result = getRoomConfig(activeRoomId.value, 'activeGroupType');
        return result;
    },
    set: (value) => {
        setRoomConfig(activeRoomId.value, 'activeGroupType', value);
    },
});
/**
 * 全局使用的 ref
 */
export const sectionAList = ref([]);
export const sectionAList = ref([]);
//#region ====================== 全局使用数据 ======================
// group 列表
export const sceneGroupList = ref([]);
// groupType 列表
export const groupTypeList = computed(() => Array.from(new Set(sceneGroupList.value.map((item) => item.group_type))));
export const groupTypeMapIcon = {
    办公助手: 'ywicon-bangong',
    知识库: 'ywicon-changyonggongjuzhishisuoyin',
    业务场景: 'ywicon-yewu',
};
/**
 * 获取全局所有数据
 */
export const getAllData = async () => {
    const res = await getSectionList();
    sceneGroupList.value = res?.groups ?? [];
};
//#endregion
src/views/project/ch/home/component/waterRight/top.vue
@@ -153,77 +153,6 @@
    border-color: #1c86ff;
    color: #fff;
}
.playInput {
    align-items: flex-start;
    width: 760px;
    position: relative;
    padding: 4px 4px 4px 12px;
    display: flex;
    -webkit-box-align: end;
    -ms-flex-align: end;
    align-items: flex-end;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    border-radius: 22px;
    border: 1px solid #00000030;
    -webkit-box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3;
    box-shadow: 0 0 0 1px transparent, 0 3px 16px 0 #dee0f3;
    -webkit-transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    -o-transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out;
    transition: border-color 0.1s ease-in-out, box-shadow 0.1s ease-in-out, -webkit-box-shadow 0.1s ease-in-out;
    background-color: #fff;
    .assembly {
        position: relative;
        align-self: flex-end;
        margin-right: 12px;
        .label {
            height: 38px;
        }
    }
    .set-input {
        position: relative;
        vertical-align: bottom;
        font-size: 14px;
        display: inline-block;
        width: 100%;
        .set-inputAnswer {
            min-height: 36px;
            height: 36px;
            padding: 3px 0;
            line-height: 20px;
            border: none;
            background-color: transparent;
            color: #333;
            font-size: 15px;
        }
        :deep(.el-input__wrapper) {
            box-shadow: unset;
        }
    }
    .upload_img {
        .imgbox {
            height: 38px;
            .set-img-icon {
                width: 38px;
                height: 38px;
                border-radius: 5px;
                transition: background-color 0.1s ease-in-out;
            }
            .send {
                width: 36px;
                height: 36px;
                border-radius: 50%;
                background-color: #2c1e1d;
                img {
                    margin: 4px 0 0 -2px;
                }
            }
        }
    }
}
</style>
<style lang="scss">
.my-pop {