Files
FiDA_Front/src/views/home/left-nav.vue

363 lines
8.8 KiB
Vue
Raw Normal View History

2026-02-03 11:11:04 +08:00
<template>
<div class="left-nav" :class="{ collapse: isCollapse }">
<div class="top">
<img class="logo-img" src="@/assets/images/logo.png" alt="FiDA" v-show="!isCollapse" />
<span class="logo-text" v-show="!isCollapse">FiDA</span>
<div class="close" @click="onCollapse">
<svg-icon name="shouqi" size="24" />
</div>
</div>
2026-02-09 14:55:55 +08:00
<button class="create-btn" @click="onCreateProject">
2026-02-03 11:11:04 +08:00
<span class="icon"><svg-icon name="add" size="16" /></span>
2026-02-04 17:00:58 +08:00
<span v-show="!isCollapse" class="text">{{ $t('Home.newProject') }}</span>
2026-02-03 11:11:04 +08:00
</button>
2026-02-04 10:11:00 +08:00
<!-- <div class="menu-item" @click="onHome">
2026-02-03 11:11:04 +08:00
<span class="icon"><svg-icon name="home" size="24" /></span>
2026-02-04 17:00:58 +08:00
<span class="title" v-show="!isCollapse">{{ $t('Home.home') }}</span>
2026-02-04 10:11:00 +08:00
</div> -->
2026-02-27 17:32:56 +08:00
<div class="menu-item" @click="onTest">
2026-03-03 11:10:43 +08:00
<span class="title">TEST</span>
2026-02-27 17:32:56 +08:00
</div>
2026-02-03 11:11:04 +08:00
<div class="menu-item" @click="onHistory" :class="{ active: showHistory }">
<span class="icon"><svg-icon name="history" size="24" /></span>
2026-02-04 17:00:58 +08:00
<span class="title" v-show="!isCollapse">{{ $t('Home.history') }}</span>
2026-02-03 11:11:04 +08:00
<span class="icon jiantou" v-show="!isCollapse"
><svg-icon name="arrow-right" size="14" />
</span>
</div>
<div class="history-list" v-show="!isCollapse && showHistory">
<div v-for="item in historyList" :key="item.name" class="history-item">
<div v-if="item.title" class="title">{{ item.name }}</div>
2026-02-05 13:55:37 +08:00
<div
v-else
class="box"
@click="onClickHistoryItem(item)"
:class="{ active: item.id == id }"
>
2026-03-03 11:10:43 +08:00
<input
v-show="item.edit"
type="text"
:value="item.name"
ref="inputRef"
:input-id="item.id"
@click.stop
@keyup.enter="(e) => onEnterHistoryItem(e, item)"
@blur="(e) => onBlurHistoryItem(e, item)"
/>
<span class="label" v-show="!item.edit">{{ item.name }}</span>
2026-02-05 13:55:37 +08:00
<el-popover
placement="right"
trigger="click"
popper-style="padding: 1rem 0.5rem;"
2026-03-03 11:10:43 +08:00
v-model:visible="item.visible"
2026-02-05 13:55:37 +08:00
>
2026-02-03 11:11:04 +08:00
<template #reference>
2026-02-05 13:55:37 +08:00
<span @click.stop class="icon"><svg-icon name="more" size="16" /></span>
2026-02-03 11:11:04 +08:00
</template>
2026-02-05 13:55:37 +08:00
<div class="history-item-menu">
2026-03-03 11:10:43 +08:00
<div class="rename" @click="onRenameHistoryItem(item)">
{{ $t('Home.rename') }}
</div>
<div class="delete" @click="onDeleteHistoryItem(item)">
{{ $t('Home.delete') }}
</div>
2026-02-03 11:11:04 +08:00
</div>
</el-popover>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
2026-03-03 11:10:43 +08:00
import { computed, ref, nextTick } from 'vue'
2026-02-03 11:11:04 +08:00
import { useRoute, useRouter } from 'vue-router'
2026-02-04 17:00:58 +08:00
import { useI18n } from 'vue-i18n'
2026-03-03 11:10:43 +08:00
import { getProjectList, updateProject, deleteProject } from '@/api/agent'
2026-02-27 16:47:02 +08:00
import { FormatDate } from '@/utils/tools'
import MyEvent from '@/utils/myEvent'
2026-02-04 17:00:58 +08:00
const { t: $t } = useI18n()
2026-02-03 11:11:04 +08:00
const route = useRoute()
const router = useRouter()
import { useGlobalStore } from '@/stores'
2026-02-05 13:55:37 +08:00
const id = computed(() => route.params.id)
2026-02-03 11:11:04 +08:00
const globalStore = useGlobalStore()
const isCollapse = computed(() => globalStore.state.homeLeftNavCollapse)
const onCollapse = () => {
globalStore.setHomeLeftNavCollapse(!isCollapse.value)
}
const showHistory = ref(true)
2026-03-03 11:10:43 +08:00
const list = ref([])
2026-02-27 16:47:02 +08:00
const historyList = computed(() => {
2026-03-03 11:10:43 +08:00
const str = 'yyyyMMdd'
const today = FormatDate(Date.now(), str)
const yesterday = FormatDate(Date.now() - 24 * 60 * 60 * 1000, str)
const todayList = []
const yesterdayList = []
const earlierChatList = []
list.value.forEach((item: any) => {
const date = FormatDate(item.updateTime * 1000, str)
if (date == today) {
todayList.push(item)
} else if (date == yesterday) {
yesterdayList.push(item)
} else {
earlierChatList.push(item)
}
})
const arr = []
if (todayList.length > 0) {
arr.push({
2026-02-27 16:47:02 +08:00
title: true,
name: $t('Home.today')
})
2026-03-03 11:10:43 +08:00
arr.push(...todayList)
2026-02-27 16:47:02 +08:00
}
2026-03-03 11:10:43 +08:00
if (yesterdayList.length > 0) {
arr.push({
2026-02-27 16:47:02 +08:00
title: true,
name: $t('Home.yesterday')
})
2026-03-03 11:10:43 +08:00
arr.push(...yesterdayList)
2026-02-27 16:47:02 +08:00
}
2026-03-03 11:10:43 +08:00
if (earlierChatList.length > 0) {
arr.push({
2026-02-27 16:47:02 +08:00
title: true,
name: $t('Home.earlierChat')
})
2026-03-03 11:10:43 +08:00
arr.push(...earlierChatList)
2026-02-03 11:11:04 +08:00
}
2026-03-03 11:10:43 +08:00
return arr
2026-02-27 16:47:02 +08:00
})
2026-02-09 14:55:55 +08:00
const onCreateProject = () => {
router.push({ name: 'mainInput' })
2026-02-03 11:11:04 +08:00
}
2026-02-09 14:55:55 +08:00
const onHome = () => {}
2026-02-27 17:32:56 +08:00
const onTest = () => {
router.push({ name: 'test' })
}
2026-02-03 11:11:04 +08:00
const onHistory = () => {
2026-02-09 14:55:55 +08:00
if (isCollapse.value) {
globalStore.setHomeLeftNavCollapse(false)
showHistory.value = true
} else {
showHistory.value = !showHistory.value
}
2026-02-03 11:11:04 +08:00
}
2026-02-05 10:45:02 +08:00
const onClickHistoryItem = (item: any) => {
2026-02-27 16:47:02 +08:00
router.push({ name: 'agent', params: { id: item.id } })
2026-02-05 10:45:02 +08:00
}
2026-03-03 11:10:43 +08:00
const inputRef = ref(null)
2026-02-05 13:55:37 +08:00
const onRenameHistoryItem = (item: any) => {
2026-03-03 11:10:43 +08:00
item.visible = false
item.edit = true
nextTick(() => {
inputRef.value.forEach((v: any) => {
const id = v.getAttribute('input-id')
if (id == item.id) v.focus()
})
})
}
const onEnterHistoryItem = (e: any, item: any) => {
e.target.blur()
}
const onBlurHistoryItem = (e: any, item: any) => {
item.edit = false
const name = e.target.value
if (!name) return console.warn('未输入名称,不允许重命名')
item.name = name
updateProject(item.id, { name }).then(() => {
GetProjectList()
})
2026-02-05 13:55:37 +08:00
}
const onDeleteHistoryItem = (item: any) => {
2026-03-03 11:10:43 +08:00
item.visible = false
deleteProject(item.id).then(() => {
GetProjectList()
if (item.id == id.value) {
router.push({ name: 'mainInput' })
}
})
2026-02-27 16:47:02 +08:00
}
const GetProjectList = async () => {
const res = await getProjectList({
page: 1,
size: 100
})
2026-03-03 11:10:43 +08:00
list.value = []
const arr = res.records || []
arr.forEach((item: any) => {
const obj = { ...item, edit: false, visible: false }
list.value.push(obj)
2026-02-27 16:47:02 +08:00
})
2026-03-03 11:10:43 +08:00
}
MyEvent.add('updateProjectList', GetProjectList)
2026-02-27 16:47:02 +08:00
GetProjectList()
2026-02-03 11:11:04 +08:00
</script>
2026-02-09 14:55:55 +08:00
2026-02-03 11:11:04 +08:00
<style lang="less" scoped>
.left-nav {
width: var(--left-nav-collapse-width, 30rem);
height: 100%;
background-color: #fff;
overflow: hidden;
display: flex;
flex-direction: column;
&,
& * {
transition: width 0.2s ease-in-out;
}
&.collapse {
--left-nav-collapse-width: 9.4rem;
--collapse-top-padding: 4.6rem 0 0 0;
--collapse-create-btn-width: 5.1rem;
--collapse-menu-item-width: 50%;
2026-03-03 11:10:43 +08:00
--collapse-menu-item-icon-margin-right: 0;
2026-02-03 11:11:04 +08:00
}
> .top {
display: flex;
align-items: center;
justify-content: center;
padding: var(--collapse-top-padding, 2.6rem 1.6rem 0 3.6rem);
> .logo-img {
width: 3.4rem;
height: auto;
margin-right: 1rem;
}
> .logo-text {
2026-02-05 13:55:37 +08:00
font-family: SemiBold;
2026-02-03 11:11:04 +08:00
font-weight: 600;
font-size: 3rem;
margin-right: auto;
}
}
> .create-btn {
margin: 4.5rem auto 2.5rem;
width: var(--collapse-create-btn-width, 23rem);
height: 5.1rem;
border-radius: 5rem;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
background-color: rgba(255, 122, 81, 1);
border: none;
outline: none;
&:active {
background-color: rgba(255, 122, 81, 0.8);
}
> .text {
font-weight: 500;
font-size: 1.8rem;
margin-left: 1rem;
}
}
> .menu-item {
width: var(--collapse-menu-item-width, 23rem);
margin: 2.5rem auto 0;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 8px;
padding: 0.9rem 0.8rem;
2026-02-27 17:32:56 +08:00
> * {
margin-right: 1.6rem;
&:last-child {
margin-right: 0;
}
}
2026-02-03 11:11:04 +08:00
&:hover {
background-color: rgba(0, 0, 0, 0.06);
}
> .title {
flex: 1;
font-weight: 500;
font-size: 2rem;
}
> .icon {
transition: transform 0.2s ease-in-out;
2026-03-03 11:10:43 +08:00
margin-right: var(--collapse-menu-item-icon-margin-right, 1.6rem);
2026-02-03 11:11:04 +08:00
}
&.active > .jiantou {
transform: rotate(90deg);
}
}
> .history-list {
flex: 1;
overflow-y: auto;
width: 23.2rem;
margin: 1rem auto 0;
> .history-item {
width: 100%;
height: 4rem;
margin-bottom: 0.4rem;
> div {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 0.8rem;
}
> .title {
font-weight: 600;
font-size: 1.6rem;
2026-02-05 13:55:37 +08:00
font-family: SemiBold;
2026-02-03 11:11:04 +08:00
}
> .box {
2026-02-05 13:55:37 +08:00
font-family: Regular;
2026-02-03 11:11:04 +08:00
border-radius: 0.8rem;
cursor: pointer;
&.active,
&:hover {
background-color: rgba(0, 0, 0, 0.06);
}
2026-02-05 13:55:37 +08:00
&.active {
font-family: SemiBold;
}
2026-02-03 11:11:04 +08:00
> .label {
flex: 1;
font-weight: 400;
font-size: 1.6rem;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
2026-03-03 11:10:43 +08:00
> input {
flex: 1;
width: 0;
height: 100%;
border: none;
outline: none;
background-color: transparent;
}
2026-02-06 16:23:22 +08:00
> .icon {
2026-02-05 13:55:37 +08:00
width: 2.5rem;
height: 2.5rem;
}
2026-02-03 11:11:04 +08:00
}
}
}
}
2026-02-05 13:55:37 +08:00
.history-item-menu {
user-select: none;
> div {
cursor: pointer;
padding: 0.5rem 1rem;
&:hover {
background-color: rgba(0, 0, 0, 0.06);
}
}
> .rename {
color: #409eff;
}
> .delete {
color: #ff4d4f;
}
}
2026-02-03 11:11:04 +08:00
</style>