wujingjing
2024-09-12 495d1510f9a9ebf1f488569f6ca24a6be56bc9f3
Revert "对接接口"

This reverts commit fbc38504507efb67e05a291f9772d3b23abf7bef.
已删除7个文件
已修改10个文件
已添加1个文件
745 ■■■■ 文件已修改
customer_list/ch/static/config/globalConfig.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/ai/chat.ts 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/Chat.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/normalTextCom/NormalTextCom.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/chatComponents/recordSetCom/types.ts 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/components/playBar/PlayBar.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/libs/markdown.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/model/Knowledge.ts 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/model/Record.ts 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/model/types.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/chat/types.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/directive/customDirective.ts 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/util.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/ch/home/Scenario.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/project/ch/home/component/waterRight/top.vue 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
customer_list/ch/static/config/globalConfig.js
@@ -7,7 +7,7 @@
    ICPLicense: '沪ICP备14049296号-2',
    WebApiUrl: {
        MainUrl: 'http:///wi.cpolar.top',
        MainUrl: 'http://101.133.133.173:97',
        AuthUrl: 'http://47.100.245.85:8190/',
    },
    SoftWareInfo: {
src/api/ai/chat.ts
ÎļþÒÑɾ³ý
src/components/chat/Chat.vue
@@ -14,15 +14,13 @@
                            <div
                                :class="{ 'bg-[#d8d8ff]': item.role === RoleEnum.assistant, 'bg-white': item.role === RoleEnum.user }"
                                class="prose text-sm rounded-[6px] p-4 leading-relaxed max-w-[100ch]"
                            >
                                <component :is="answerTypeMapCom[item.content.type]" :data="item.content.values" />
                            </div>
                            <!-- <div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 space-x-2 mr-2 mt-2">
                                v-html="md.render(item.content)"
                            ></div>
                            <div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 space-x-2 mr-2 mt-2">
                                <SvgIcon class="cursor-pointer" name="ele-CopyDocument" @click="copyClick(item.content)" />
                                <SvgIcon class="cursor-pointer" name="ywicon icon-dianzan" />
                                <SvgIcon class="cursor-pointer" :size="12" name="ywicon icon-buzan" />
                            </div> -->
                            </div>
                        </div>
                        <Loding v-else />
@@ -39,25 +37,20 @@
<script setup lang="ts">
import cryptoJS from 'crypto-js';
import { ElMessage } from 'element-plus';
import { nextTick, onMounted, ref, watch } from 'vue';
import useClipboard from 'vue-clipboard3';
import Loding from './components/Loding.vue';
import { RecordSet } from './model/Record';
import type { ChatContent } from './model/types';
import { AnswerType, RoleEnum, answerTypeMapCom, roleImageMap, type ChatMessage } from './model/types';
import { QuestionAi } from '/@/api/ai/chat';
import { md } from './libs/markdown';
import { RoleEnum, roleImageMap, type ChatMessage } from './types';
import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue';
import router from '/@/router';
import { activeChatRoom } from '/@/stores/chatRoom';
import { ElMessage } from 'element-plus';
import router from '/@/router';
let apiKey = '';
let isConfig = ref(false);
let isTalking = ref(false);
let messageContent = ref<ChatContent>({
    type: AnswerType.Text,
    values: '',
});
let messageContent = ref('');
const chatListDom = ref<HTMLDivElement>();
const decoder = new TextDecoder('utf-8');
const roleAlias = { user: 'ME', assistant: 'ChatGPT', system: 'System' };
@@ -86,38 +79,11 @@
        });
        return;
    }
    messageContent.value.values = activeChatRoom.value.title;
    messageContent.value = activeChatRoom.value.title;
    sendOrSave();
});
const questionAi = async (text) => {
    const res = await QuestionAi({
        question: text,
    });
    let content: ChatContent = {
        type: AnswerType.Text,
        values: '发生错误!',
    };
    switch (res.answer_type) {
        case AnswerType.RecordSet:
            content = {
                type: AnswerType.RecordSet,
                values: res.values,
            };
            break;
        case AnswerType.Text:
            content = {
                type: AnswerType.Text,
                values: res.values,
            };
            break;
        default:
            break;
    }
    return content;
};
const sendChatMessage = async (content: ChatContent = messageContent.value) => {
const sendChatMessage = async (content: string = messageContent.value) => {
    try {
        isTalking.value = true;
        // if (messageList.value.length === 0) {
@@ -125,27 +91,23 @@
        // }
        messageList.value.push({ role: RoleEnum.user, content });
        clearMessageContent();
        messageList.value.push({ role: RoleEnum.assistant, content });
        messageList.value.push({ role: RoleEnum.assistant, content: '' });
        // const { body, status } = await chat(messageList.value, getAPIKey());
        // if (body) {
        //   const reader = body.getReader();
        //   await readStream(reader, status);
        // }
        // const a = new Promise<string>((resolve) => {
        //     setTimeout(() => {
        //         resolve('你好,我是AI语言模型 ');
        //     }, 500);
        // });
        const a = new Promise<string>((resolve) => {
            setTimeout(() => {
                resolve('你好,我是AI语言模型 ');
            }, 500);
        });
        let msg:ChatContent = {
            type:AnswerType.Text,
            values:''
        };
        msg = await questionAi(content);
        const msg = await a;
        appendLastMessageContent(msg);
    } catch (error: any) {
        appendLastMessageContent('发生错误!');
        appendLastMessageContent(error);
    } finally {
        isTalking.value = false;
    }
@@ -185,22 +147,44 @@
    }
};
const appendLastMessageContent = (content: ChatContent) => {
    messageList.value.push(
    )
};
const appendLastMessageContent = (content: string) => (messageList.value[messageList.value.length - 1].content += content);
const sendOrSave = () => {
    if (!messageContent.value) return;
    if (!messageContent.value.length) return;
    if (activeChatRoom.value.isInitial) {
        activeChatRoom.value.title = messageContent.value.values;
        activeChatRoom.value.title = messageContent.value;
        activeChatRoom.value.isInitial = false;
    }
    sendChatMessage();
    if (isConfig.value) {
        if (saveAPIKey(messageContent.value.trim())) {
            switchConfigStatus();
        }
        clearMessageContent();
    } else {
        sendChatMessage();
    }
};
const clickConfig = () => {
    if (!isConfig.value) {
        messageContent.value = getAPIKey();
    } else {
        clearMessageContent();
    }
    switchConfigStatus();
};
const getSecretKey = () => 'lianginx';
const saveAPIKey = (apiKey: string) => {
    if (apiKey.slice(0, 3) !== 'sk-' || apiKey.length !== 51) {
        alert('API Key é”™è¯¯ï¼Œè¯·æ£€æŸ¥åŽé‡æ–°è¾“入!');
        return false;
    }
    const aesAPIKey = cryptoJS.AES.encrypt(apiKey, getSecretKey()).toString();
    localStorage.setItem('apiKey', aesAPIKey);
    return true;
};
const getAPIKey = () => {
    if (apiKey) return apiKey;
@@ -211,7 +195,7 @@
const switchConfigStatus = () => (isConfig.value = !isConfig.value);
const clearMessageContent = () => (messageContent.value = null);
const clearMessageContent = () => (messageContent.value = '');
const scrollToBottom = () => {
    if (!chatListDom.value) return;
src/components/chat/chatComponents/normalTextCom/NormalTextCom.vue
ÎļþÒÑɾ³ý
src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue
ÎļþÒÑɾ³ý
src/components/chat/chatComponents/recordSetCom/types.ts
ÎļþÒÑɾ³ý
src/components/chat/components/playBar/PlayBar.vue
@@ -6,13 +6,7 @@
            </el-button>
        </div>
        <div class="set-input">
            <el-input
                v-elInputFocus
                @keydown="enterInput"
                v-model="inputValue"
                placeholder="在这里输入您的问题开始和AI对话"
                class="set-inputAnswer"
            />
            <el-input v-elInputFocus @keydown.enter="isTalking || emits('sendClick')" v-model="inputValue" placeholder="在这里输入您的问题开始和AI对话" class="set-inputAnswer" />
        </div>
        <div class="h100 flex items-center">
            <div class="upload_img space-y">
@@ -40,22 +34,11 @@
const emits = defineEmits(['sendClick']);
const props = defineProps(['isTalking']);
defineProps(['isTalking'])
const inputValue = defineModel({
    type: String,
});
const enterInput = (e) => {
    if (props.isTalking) return;
    if (!e.shiftKey && e.keyCode == 13) {
        e.cancelBubble = true; //ie阻止冒泡行为
        e.stopPropagation(); //Firefox阻止冒泡行为
        e.preventDefault(); //取消事件的默认动作*换行
        //以下处理发送消息代码
        emits('sendClick');
    }
};
    type:String
})
</script>
<style scoped lang="scss">
.set-waterTitle {
src/components/chat/libs/markdown.ts
@@ -6,7 +6,6 @@
    typographer: true,
    breaks: true,
    langPrefix: 'language-',
    html:true,
    // ä»£ç é«˜äº®
    highlight(str, lang) {
        if (lang && highlight.getLanguage(lang)) {
src/components/chat/model/Knowledge.ts
ÎļþÒÑɾ³ý
src/components/chat/model/Record.ts
ÎļþÒÑɾ³ý
src/components/chat/model/types.ts
ÎļþÒÑɾ³ý
src/components/chat/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
import userPic from './images/user.svg';
import assistantPic from './images/assistant.jpg';
export const enum RoleEnum {
    user = 'user',
    assistant = 'assistant',
    system = 'system',
}
export interface ChatMessage {
    role: RoleEnum;
    content: string;
}
export const roleImageMap = {
    [RoleEnum.user]: userPic,
    [RoleEnum.assistant]: assistantPic,
    [RoleEnum.system]: userPic,
};
src/directive/customDirective.ts
@@ -53,13 +53,13 @@
    });
}
export const eleFocusDirective = (app: App) => {
    app.directive('elInputFocus', {
        mounted: (el) => {
            el.querySelector('input.el-input__inner')?.focus();
        },
    });
};
export const eleFocusDirective =(app:App)=>{
    app.directive('elInputFocus',{
        mounted:(el)=>{
            el.querySelector('input.el-input__inner')?.focus()
        }
    })
}
/**
 * è‡ªå®šä¹‰æ‹–动指令
src/utils/request.ts
@@ -1,8 +1,8 @@
import type { AxiosInstance, AxiosRequestConfig } from 'axios';
import axios from 'axios';
import { ElMessage } from 'element-plus';
import { AUTH_URL, MAIN_URL, SECONDARY_URL } from '/@/constants';
import { Local, Session } from '/@/utils/storage';
import { AUTH_URL, MAIN_URL, SECONDARY_URL } from '/@/constants';
// import JSONbig from 'json-bigint';
//#region ====================== åŽç«¯ res.Code ======================
@@ -30,7 +30,7 @@
// //     è¶…时(暂不使用)
// TimeOut = -5
//#endregion
const initRequestInterceptor = (request: AxiosInstance,isAuth=false) => {
const initRequestInterceptor = (request: AxiosInstance) => {
    // æ·»åŠ è¯·æ±‚æ‹¦æˆªå™¨
    request.interceptors.request.use(
        (config) => {
@@ -42,13 +42,8 @@
            // èŽ·å–æœ¬åœ°çš„ token
            const accessToken = Local.get(accessTokenKey);
            if (accessToken) {
                // å°† token æ·»åŠ åˆ°è¯·æ±‚æŠ¥æ–‡å¤´ä¸­â€˜
                if(isAuth){
                    config.headers!['Authorization'] = `Bearer ${accessToken}`;
                }else{
                    config.headers['Referrer-Policy'] = undefined;
                }
                // å°† token æ·»åŠ åˆ°è¯·æ±‚æŠ¥æ–‡å¤´ä¸­
                config.headers!['Authorization'] = `Bearer ${accessToken}`;
                // åˆ¤æ–­ accessToken æ˜¯å¦è¿‡æœŸ
                const jwt: any = decryptJWT(accessToken);
@@ -122,12 +117,6 @@
                Local.set(accessTokenKey, accessToken);
                Local.set(refreshAccessTokenKey, refreshAccessToken);
            }
            if (!serve.json_ok && !isAuth) {
                // ElMessage.warning(serve.json_msg)
                throw new Error('响应错误');
            }
            // å“åº”拦截及自定义处理
            if (serve.data === 401) {
                clearAccessTokens();
@@ -169,17 +158,16 @@
    baseURL: MAIN_URL,
    timeout: 50000,
    headers: { 'Content-Type': 'application/json;charset=utf-8 ' },
    // transformResponse: [
    //     function (data) {
    //         const JSONbigToString = JSONbig({ storeAsString: true });
    //         // å°†Long类型数据转换为字符串
    //         return JSONbigToString.parse(data);
    //     },
    // ],
});
const authService = axios.create({
    // baseURL: MAIN_URL,
    timeout: 50000,
    headers: { 'Content-Type': 'application/json;charset=utf-8 ' },
});
initRequestInterceptor(service);
initRequestInterceptor(authService,true)
export function secondaryRequest(config: AxiosRequestConfig<any>) {
    return service({
@@ -192,7 +180,7 @@
 * ç”¨äºŽè®¿é—®ç™»å½•接口
 */
export function authRequest(config: AxiosRequestConfig<any>) {
    return authService({
    return service({
        ...config,
        baseURL: AUTH_URL,
    });
src/utils/util.ts
@@ -11,42 +11,6 @@
import axios from 'axios';
import { MAIN_URL } from '../constants';
/**
 * æ™®é€šå¯¹è±¡è½¬ä¸º formData
 * @param obj
 */
export const toFormData = (obj: any) => {
    const formData = new FormData();
    const addFormData = (subObj, prePrefix = '', isArray = false) => {
        for (const key in subObj) {
            if (Object.prototype.hasOwnProperty.call(subObj, key)) {
                const value = subObj[key];
                let currentKey = '';
                if (prePrefix === '') {
                    currentKey = key;
                } else if (isArray) {
                    currentKey = `${prePrefix}[${key}]`;
                } else {
                    currentKey = `${prePrefix}.${key}`;
                }
                if (value != null && Array.isArray(value) && value.length > 0) {
                    addFormData(value, currentKey, true);
                } else if (value != null && typeof value === 'object' && Object.values(value).length > 0) {
                    addFormData(value, currentKey, false);
                } else {
                    formData.append(currentKey, value);
                }
            }
        }
    };
    addFormData(obj);
    return formData;
};
/**
 * @description å½“碰到 JSON ä¸­å­˜åœ¨è¿‡é•¿çš„æ•°å­—时,使用 JSONbigString è§£æžï¼Œæ•°å­—会转为字符串处理
 * ç”¨æ³•:JSONbigString.parse(jsonStr))
src/views/project/ch/home/Scenario.vue
@@ -146,6 +146,7 @@
});
//切换到应用场景详情的事件
const changeApp = (item: any) => {
    console.log('🚀 ~ item:', item);
    if (item.ID === 2) {
        router.push({
            name: 'ScenarioDetails',
src/views/project/ch/home/component/waterRight/top.vue
@@ -4,17 +4,13 @@
        <p class="set-waterTitle"><strong>WI æ°´åŠ¡æ™ºèƒ½ä¸“å®¶</strong>智慧水务助手</p>
    </div>
    <div class="flex items-center pc-roleList">
        <div v-for="(item, index) in llmList" :key="item.logicId" class="flex items-center pl-6" @click="handleClick(item)">
            <div class="modelItem cursor-pointer flex items-center" :class="{ modelItemActive: item.logicId === activeLLMId }">
                <img :src="item.icon" alt="icon" class="set-icon box-border" />
                <span>{{ item.logicTitle }}</span>
            </div>
            <!-- <el-tooltip :content="item.Content" placement="top" effect="light" popper-class="my-pop">
                <div class="modelItem cursor-pointer flex items-center " :class="{ modelItemActive: item.ID === state.activeRole }">
        <div v-for="(item, index) in state.roleList" :key="index" class="flex items-center pl-6" @click="handleClick(item)">
            <el-tooltip :content="item.Content" placement="top" effect="light" popper-class="my-pop">
                <div class="modelItem cursor-pointer flex items-center" :class="{ modelItemActive: item.ID === state.activeRole }">
                    <img :src="item.Icon" alt="icon" class="set-icon box-border" />
                    <span>{{ item.Title }}</span>
                </div>
            </el-tooltip> -->
            </el-tooltip>
        </div>
        <div class="flex items-center cursor-pointer pl-5">
            <div class="modelItem cursor-pointer flex items-center">
@@ -27,8 +23,7 @@
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue';
import { GetLLMList, SetLLM } from '/@/api/ai/chat';
import { reactive, ref } from 'vue';
import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue';
import router from '/@/router';
import { activeChatRoom } from '/@/stores/chatRoom';
@@ -36,10 +31,11 @@
const inputValue = ref('');
const sendClick = () => {
    if (!inputValue.value) return;
    if(!inputValue.value) return;
    activeChatRoom.value.title = inputValue.value;
    router.push({
        name: 'AskAnswer',
    });
};
let state = reactive({
@@ -66,47 +62,11 @@
        },
    ],
    activeRole: 0,
    inputAnswer: '',
});
const activeLLMId = ref();
const llmList = ref([]);
const iconList = ['/static/images/wave/Glm.jpg', '/static/images/wave/Glm.jpg', '/static/images/wave/Glm.jpg'];
const getLLMList = async () => {
    const res = await GetLLMList();
    const resData = (res?.llm_list || []) as any[];
    llmList.value = resData.map((item, index) => ({
        get logicId() {
            return this.logicModel.id;
        },
        get logicTitle() {
            return this.logicModel.title;
        },
        icon: iconList[index],
        logicModel: {
            ...item,
        },
    }));
    const first = llmList.value?.[0];
    first && setLLm(first.logicId);
};
const setLLm = async (llmId: string) => {
    const res = await SetLLM({
        llm: llmId,
    });
    activeLLMId.value = llmId;
    return true;
};
const handleClick = (item) => {
    setLLm(item.logicId);
    state.activeRole = item.id;
};
onMounted(() => {
    getLLMList();
});
</script>
<style scoped lang="scss">
.set-waterTitle {
vite.config.ts
@@ -35,14 +35,14 @@
            host: '0.0.0.0',
            port: env.VITE_PORT as unknown as number,
            open: JSON.parse(env.VITE_OPEN),
            hmr: false,
            hmr: true,
            proxy: {
                // '/wiai':{
                //     target:'http://wi.cpolar.top',
                //     ws: true,
                //     changeOrigin: true,
                //     rewrite: (path) => path.replace(/^\/wiai/, ''),
                // }
                '/gitee': {
                    target: 'https://gitee.com',
                    ws: true,
                    changeOrigin: true,
                    rewrite: (path) => path.replace(/^\/gitee/, ''),
                },
            },
        },
        build: {