Browse Source

🎈 perf: 针对重工乐跑进行优化

Pchen. 4 months ago
parent
commit
2c76b02d6b

BIN
public/background.webm


+ 0 - 0
public/lepao.pac


BIN
public/runforge-ios-root.cer


+ 0 - 103
src/api/ai.js

@@ -1,103 +0,0 @@
-import request from '@/utils/request'
-
-const api = {
-    ScanRepo: '/AI/ScanRepo',
-    GetScanTaskList: '/AI/GetScanTaskList',
-    GetScanTaskDetail: '/AI/GetScanTaskDetail',
-    GetCommitSummary: '/AI/GetCommitSummary',
-    SummaryCommit: '/AI/SummaryCommit',
-    SummaryFile: '/AI/SummaryFile',
-    GetFileSummary: '/AI/GetFileSummary',
-    GetAIChatMessages: '/AI/GetAIChatMessages',
-    GetAIChatMessage: '/AI/GetAIChatMessage',
-    DeleteAIChatMessages: '/AI/DeleteAIChatMessages',
-    AIChat: '/AI/Chat'
-}
-
-export function ScanRepo(parameter) {
-    return request({
-        url: api.ScanRepo,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function GetScanTaskList(parameter) {
-    return request({
-        url: api.GetScanTaskList,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function GetScanTaskDetail(parameter) {
-    return request({
-        url: api.GetScanTaskDetail,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function GetCommitSummary(parameter) {
-    return request({
-        url: api.GetCommitSummary,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function SummaryCommit(parameter) {
-    return request({
-        url: api.SummaryCommit,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function SummaryFile(parameter) {
-    return request({
-        url: api.SummaryFile,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function GetFileSummary(parameter) {
-    return request({
-        url: api.GetFileSummary,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function GetAIChatMessages(parameter) {
-    return request({
-        url: api.GetAIChatMessages,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function GetAIChatMessage(parameter) {
-    return request({
-        url: api.GetAIChatMessage,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function DeleteAIChatMessages(parameter) {
-    return request({
-        url: api.DeleteAIChatMessages,
-        method: 'get',
-        params: parameter
-    })
-}
-
-export function AIChat(parameter) {
-    return request({
-        url: api.AIChat,
-        method: 'post',
-        data: parameter
-    })
-}

+ 0 - 352
src/components/AIChat/index.vue

@@ -1,352 +0,0 @@
-<template>
-    <a-drawer :visible="props.visible" class="drawer" width="570px" @cancel="closeAI" placement="left" :footer="false">
-        <template #title>
-            <div class="aiTitle">
-                <img alt="AI" src="@/assets/ai.svg" height="25">
-                <span>AI助手</span>
-                <a-button size="small" class="button" @click="deleteMessages">清空记录</a-button>
-            </div>
-        </template>
-        <div class="container">
-            <div class="messages" ref="messagesContainer">
-                <a-spin :loading="messagesLoading">
-                    <div v-for="(item, index) in messages">
-                        <div class="time"
-                            v-if="!messages[index - 1] || (messages[index].time - messages[index - 1].time) > 300000">{{
-                                stramptoTime(item.time) }}</div>
-                        <div :class="['message', item.type === 'user' ? 'right' : 'left']">
-                            <a-avatar class="avatar">
-                                <img alt="avatar" src="@/assets/img/avatar/assistant.png" v-if="item.type !== 'user'" />
-                                <img alt="avatar" :src="user.avatar" v-else-if="item.type === 'user'" />
-                            </a-avatar>
-                            <a-dropdown trigger="contextMenu" alignPoint :style="{ display: 'block', zIndex: 99 }">
-                                <div :class="['content', item.type === 'user' ? 'user' : 'ai']"
-                                    v-html="renderMarkdown(item.content)">
-                                </div>
-                                <template #content>
-                                    <a-doption>
-                                        <icon-play-arrow /> 打开仓库
-                                    </a-doption>
-                                </template>
-                            </a-dropdown>
-                        </div>
-                    </div>
-                </a-spin>
-            </div>
-
-            <div class="inputBox">
-                <a-textarea placeholder="您的专属AI助手~" :max-length="300" :auto-size="{
-                    minRows: 1,
-                    maxRows: 6
-                }" allow-clear v-model="input" />
-                <a-button type="primary" :loading="send" @click="sendMessage">发送</a-button>
-            </div>
-        </div>
-    </a-drawer>
-</template>
-
-<script setup>
-import { ref, onMounted, nextTick, watch, onUnmounted } from 'vue'
-import { Message, Modal } from '@arco-design/web-vue'
-import { eventBus } from '@/utils/eventBus'
-import { AIChat, GetAIChatMessages, GetAIChatMessage, DeleteAIChatMessages } from '@/api/ai'
-import { useUserStore } from '@/store/modules/user'
-import MarkdownIt from 'markdown-it'
-
-const md = new MarkdownIt()
-
-const renderMarkdown = (text) => {
-    return md.render(text || '')
-}
-
-const props = defineProps({
-    visible: {
-        type: Boolean,
-        default: false
-    }
-})
-
-const user = ref('')
-const input = ref('')
-const messagesLoading = ref(false)
-const send = ref(false)
-const messages = ref([])
-const msgid = ref('')
-const newIndex = ref()
-
-const messagesContainer = ref(null)
-
-const scrollToBottom = () => {
-    if (messagesContainer.value) {
-        // 等 DOM 渲染完成再滚动
-        nextTick(() => {
-            messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
-        })
-    }
-}
-
-const getAIChatMessages = async () => {
-    try {
-        messagesLoading.value = true
-        const res = await GetAIChatMessages()
-        if (!res || res.code !== 0)
-            return Message.error(`获取历史对话消息失败!${res?.msg ?? ''}`)
-        messages.value = res.data
-        messages.value.push({
-            type: 'system', time: new Date().getTime(), content: '你好!我是你的专属AI智能助手“小吉”,你可以问我任何问题哦~~\n试着问问:\n- 我拥有哪些Git仓库?\n- 仓库GitNexus最近一次提交的信息是什么?\n- 请对比electron仓库的最后两次提交。'
-        })
-    } catch (error) {
-        Message.error(`获取历史对话消息失败!`)
-    } finally {
-        scrollToBottom()
-        messagesLoading.value = false
-    }
-}
-
-const getAIChatMessage = async () => {
-    try {
-        const res = await GetAIChatMessage({ id: msgid.value })
-        if (!res || res.code !== 0) {
-            send.value = false
-            return messages.value[newIndex.value].content = '获取对话消息失败,请稍后再试'
-        }
-
-        if (!res.data)
-            return
-
-        stopPolling()
-        messages.value[newIndex.value].content = ''
-        for (let i = 0; i < res.data.length; i++) {
-            await new Promise(resolve => setTimeout(resolve, 30))
-            messages.value[newIndex.value].content += res.data[i]
-            scrollToBottom()
-        }
-        send.value = false
-    } catch (error) {
-        Message.error(`获取对话消息失败!`)
-    } finally {
-        scrollToBottom()
-    }
-}
-
-let timer = null
-
-// 轮询
-const startPolling = () => {
-    if (!timer) {
-        timer = setInterval(async () => {
-            await getAIChatMessage()
-        }, 1000)
-    }
-}
-
-// 停止轮询
-const stopPolling = () => {
-    if (timer) {
-        clearInterval(timer)
-        timer = null
-    }
-    send.value = false
-}
-
-const sendMessage = async () => {
-    if (input.value === '') return
-    send.value = true
-    let content = input.value
-    input.value = ''
-    try {
-        messages.value.push({ type: 'user', time: new Date().getTime(), content })
-        newIndex.value = messages.value.push({ type: 'ai', time: new Date().getTime(), content: '小吉正在思考哦~请稍候...' }) - 1
-        scrollToBottom()
-        const res = await AIChat({ message: content })
-        if (!res || res.code !== 0) {
-            send.value = false
-            return messages.value[newIndex.value].content = '获取对话消息失败,请稍后再试'
-        }
-
-        msgid.value = res.id
-        startPolling()
-    } catch (error) {
-        console.log(error)
-        Message.error('获取对话消息失败!请稍后再试')
-    }
-}
-
-const closeAI = () => {
-    eventBus.emit('closeAI')
-}
-
-const getuser = async () => {
-    const userStore = useUserStore()
-    let userInfo = await userStore.getInfo()
-    user.value = userInfo
-}
-
-onMounted(async () => {
-    getuser()
-    await getAIChatMessages()
-})
-
-// 组件销毁时停止轮询
-onUnmounted(() => {
-    stopPolling()
-})
-
-watch(
-    () => props.visible,
-    (val) => {
-        if (val) {
-            nextTick(() => {
-                scrollToBottom()
-            })
-        }
-    }
-)
-
-const stramptoTime = (time) => {
-    return new Date(time).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })
-}
-
-const deleteMessages = () => {
-    Modal.confirm({
-        title: '清空消息记录',
-        content: '您即将清空所有消息记录,是否继续?',
-        onOk: async () => {
-            const res = await DeleteAIChatMessages()
-            if (!res || res.code !== 0)
-                return Message.error('清空消息记录失败!')
-            getAIChatMessages()
-            Message.success('清空消息记录成功!')
-        },
-        onCancel: () => {
-
-        }
-    })
-}
-
-</script>
-
-<style lang="less" scoped>
-.container {
-    display: flex;
-    flex-direction: column;
-    height: calc(100% + 20px);
-    gap: 10px;
-    margin-top: -20px;
-
-    /* 对于 Webkit 浏览器(Chrome、Safari) */
-    .messages::-webkit-scrollbar {
-        width: 8px;
-    }
-
-    .messages::-webkit-scrollbar-track {
-        background: transparent;
-    }
-
-    .messages::-webkit-scrollbar-thumb {
-        background-color: rgba(0, 0, 0, 0.2);
-        /* 滚动条滑块背景 */
-        border-radius: 10px;
-        /* 滚动条滑块圆角 */
-    }
-
-    .messages::-webkit-scrollbar-thumb:hover {
-        background-color: rgba(0, 0, 0, 0.3);
-        /* 滚动条滑块悬停时的背景 */
-    }
-
-    .messages {
-        flex: 1;
-        overflow-y: auto;
-        padding: 10px;
-        display: flex;
-        flex-direction: column;
-
-        .time {
-            color: #888;
-            font-size: 0.9em;
-            text-align: center;
-            margin: 10px 0 0;
-        }
-
-        .message {
-            display: flex;
-            margin-top: 10px;
-
-            &.right {
-                flex-direction: row-reverse;
-                justify-content: end;
-            }
-
-            .avatar {
-                user-select: none;
-                width: 36px;
-                height: 36px;
-                background-color: #fff;
-            }
-
-
-            /* 对于 Webkit 浏览器(Chrome、Safari) */
-            .content::-webkit-scrollbar {
-                height: 6px;
-            }
-
-            .content::-webkit-scrollbar-track {
-                background: transparent;
-            }
-
-            .content::-webkit-scrollbar-thumb {
-                background-color: rgba(0, 0, 0, 0.2);
-                /* 滚动条滑块背景 */
-                border-radius: 10px;
-                /* 滚动条滑块圆角 */
-            }
-
-            .content::-webkit-scrollbar-thumb:hover {
-                background-color: rgba(0, 0, 0, 0.3);
-                /* 滚动条滑块悬停时的背景 */
-            }
-
-            .content {
-                max-width: 70%;
-                padding: 0 14px;
-                border-radius: 10px;
-                margin: 0 10px;
-                font-size: 14px;
-                line-height: 1.5;
-                word-break: break-word;
-                overflow-x: auto;
-
-                &.user {
-                    background-color: #4e88ff;
-                    color: white;
-                }
-
-                &.ai {
-                    background-color: #eee;
-                    color: #333;
-                }
-            }
-        }
-
-    }
-
-    .inputBox {
-        display: flex;
-        gap: 10px;
-        min-height: 15px;
-    }
-}
-
-.aiTitle {
-    display: flex;
-    font-size: 1.1em;
-    gap: 10px;
-    width: 100%;
-
-    .button {
-        position: absolute;
-        left: 75%;
-    }
-}
-</style>

+ 0 - 97
src/components/ChangeBranch/index.vue

@@ -1,97 +0,0 @@
-<template>
-    <a-drawer :visible="props.visible" class="drawer" width="520px" v-if="status" @cancel="closeChangeBranch"
-    placement="left" :footer="false">
-    <template #title><icon-swap /> 切换分支</template>
-    <a-list hoverable>
-        <a-list-item v-for="(item, index) in props.status.branches" :key="index">
-            <div class="branch-list">
-                <div class="icon">
-                    <icon-branch :size="25" />
-                </div>
-                <div class="info">
-                    <span class="title">
-                        {{ item.name }}
-                    </span>
-                    <span class="label">
-                        <a-tag size="small">{{ item.commit }}</a-tag>
-                        {{ item.label }}
-                    </span>
-                </div>
-                <div class="button">
-                    <a-button type="primary" size="small" v-if="item.name !== status.status.current"
-                        @click="ChangeBranch(item.name)">切换</a-button>
-                    <a-button type="text" size="small" v-else>当前</a-button>
-                </div>
-            </div>
-        </a-list-item>
-    </a-list>
-</a-drawer>
-</template>
-
-<script setup>
-import { Notification, Message } from '@arco-design/web-vue'
-import { useRepoStore } from '@/store'
-import { eventBus } from '@/utils/eventBus'
-
-const repoStore = useRepoStore()
-const props = defineProps({
-    id: {
-        type: Number
-    },
-    visible: {
-        type: Boolean,
-        default: false
-    },
-    status: {
-        type: Object
-    }
-})
-
-const emit = defineEmits(['changeBegin', 'changeFail', 'close'])
-
-const ChangeBranch = async (branch) => {
-    try {
-        emit('changeBegin')
-        emit('close')
-        await repoStore.ChangeBranch(props.id, branch )
-        Message.success(`已切换至分支 ${branch}`)
-        eventBus.emit('changeOK')
-    } catch (error) {
-        console.error(error)
-        Notification.error({
-            title: '切换仓库分支失败!',
-            content: error.message || '请稍后再试'
-        })
-        emit('changeFail')
-    } 
-}
-
-const closeChangeBranch = () => {
-    emit('close')
-}
-
-</script>
-
-<style lang="less" scoped>
-.branch-list {
-    display: flex;
-    min-height: 60px;
-    align-items: center;
-
-    .info {
-        display: flex;
-        flex-direction: column;
-        margin-left: 15px;
-        margin-right: 15px;
-
-
-        .title {
-            font-size: 1.3em;
-        }
-    }
-
-    .button {
-        margin-left: auto;
-    }
-}
-</style>

+ 0 - 113
src/components/CodeBlock/index.vue

@@ -1,113 +0,0 @@
-<template>
-    <div class="code-container">
-        <div class="copy" v-if="!copied" @click="copyCode">复制</div>
-        <div class="copy" v-else><icon-check-circle /> 复制成功!</div>
-        <div class="line">
-            <span class="line-number" v-for="num in line">{{ num + props.startLine - 1 }}</span>
-        </div>
-        <highlightjs :code="code" class="code" />
-    </div>
-</template>
-
-<script setup>
-import { ref, computed, onMounted } from 'vue'
-import hljsVuePlugin from '@highlightjs/vue-plugin'
-// import { useThemeStore } from '@/store'
-import 'highlight.js/lib/common'
-import 'highlight.js/styles/atom-one-light.css'
-
-// const themeStore = useThemeStore()
-const props = defineProps({
-    code: {
-        type: String,
-        required: true
-    },
-    startLine: {
-        type: Number,
-        default: 1
-    }
-})
-const copied = ref(false)
-
-const highlightjs = hljsVuePlugin.component
-const line = computed(() => {
-    const lines = props.code.split('\n')
-    if (lines[lines.length - 1] == '')
-        return lines.length - 1
-    return lines.length
-})
-
-function copyCode() {
-  navigator.clipboard.writeText(props.code).then(() => {
-    copied.value = true
-    setTimeout(() => {
-      copied.value = false
-    }, 2000)
-  })
-}
-
-// function loadThemeCSS(theme) {
-//     import(`highlight.js/styles/${theme}.css`) 
-// }
-
-// onMounted(() => {
-//   loadThemeCSS(themeStore.getTheme())
-// })
-
-</script>
-
-<style scoped lang="less">
-.code-container {
-    position: relative;
-    display: flex;
-    padding: 0;
-    white-space: pre;
-    overflow-x: auto;
-
-    .copy {
-        position: absolute;
-        right: 6px;
-        top: 19px;
-        background: #eee;
-        padding: 4px 10px;
-        font-size: 12px;
-        border-radius: 4px;
-        cursor: pointer;
-        display: none;
-        user-select: none;
-    }
-
-    .code {
-        line-height: 1.5em;
-        margin-bottom: 10px;
-        width: 100%;
-        overflow-x: auto;
-    }
-
-    .line {
-        display: flex;
-        flex-direction: column;
-        line-height: 1.5em;
-        background-color: #f0f0f0;
-        margin-bottom: 10px;
-        margin-top: 15px;
-        padding-top: 15px;
-
-        .line-number {
-            user-select: none;
-            display: inline-block;
-            min-width: 35px;
-            color: #888;
-            text-align: center;
-            font-family: 'Fira Code', 'JetBrains Mono', Menlo, Consolas, 'Courier New', monospace;
-        }
-    }
-}
-
-.code-container:hover {
-    .copy {
-        display: block;
-    }
-}
-
-</style>

+ 1 - 1
src/pages/Main/Main.vue

@@ -2,7 +2,7 @@
     <div id="section1" class="section root">
         <div class="videocontainer">
             <video class="fullscreenvideo" playsinline="" autoplay="" muted="" loop=""
-                src="/background.webm" type="video/mp4" />
+                src="//xxoo365.top/background.webm" type="video/mp4" />
             <div class="overlay" />
         </div>
         <Header color="white" />