YingXingAI/pages/home/history/index.vue

684 lines
17 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="history-page">
<header-bar title="历史记录" @leftClick="handleLeftClick"></header-bar>
<view class="tab-container">
<view class="custom-tab">
<view
v-for="tab in tabList"
:key="tab.id"
:class="['tab-item', { active: activeTab === tab.id }]"
@click="switchTab(tab.id)"
>
<text class="tab-text">{{ tab.name }}</text>
<view class="tab-underline" v-if="activeTab === tab.id"></view>
</view>
</view>
<view class="more-icon-container" @click="toggleMoreMenu">
<image
class="more-icon"
src="/static/common/images/icon-more.png"
mode="scaleToFill"
></image>
</view>
<!-- 右上角弹出菜单:批量删除 -->
<view v-if="isMoreMenuVisible" class="more-menu" @click.stop>
<view class="menu-card" @click="handleBatchDeleteClick">
<!-- <image
class="menu-icon"
src="/static/common/images/icon_delete.png"
mode="widthFix"
/> -->
<u-icon name="trash" color="#FF647D" size="28"></u-icon>
<text class="menu-text">批量删除</text>
</view>
</view>
</view>
<!-- 点击其他区域关闭弹层 -->
<view v-if="isMoreMenuVisible" class="overlay" @click="hideMoreMenu"></view>
<!-- 内容区域包装器 -->
<view class="content-wrapper">
<!-- 历史记录列表(按日期分组,日期固定在上方) -->
<view class="history-list">
<view
class="date-group"
v-for="(group, groupIndex) in currentHistoryList"
:key="groupIndex"
>
<view class="date-header">{{ group.id }}</view>
<view
class="history-item"
v-for="item in group.conversation"
:key="item.id"
>
<!-- 批量删除模式下的选择框 -->
<view
class="item-checkbox"
v-if="isBatchDeleteMode"
@click="toggleItemSelection(item.id)"
>
<view
class="checkbox"
:class="{ checked: selectedItems.includes(item.id) }"
>
<text class="checkmark" v-if="selectedItems.includes(item.id)"
>✓</text
>
</view>
</view>
<!-- 历史记录内容 -->
<view class="item-content">
<view class="item-header">
<view class="item-icon">
<image
class="icon-image"
src="/static/common/images/icon_chat2.png"
/>
</view>
<view class="item-title">{{ item.title }}</view>
</view>
<!-- <view class="item-description">{{ item.content }}</view> -->
</view>
</view>
</view>
</view>
</view>
<!-- 批量删除操作栏 -->
<view class="batch-actions" v-if="isBatchDeleteMode">
<view class="select-all-container" @click="toggleSelectAll">
<view class="checkbox" :class="{ checked: selectAll }">
<text class="checkmark" v-if="selectAll">✓</text>
</view>
<text class="select-all-text">全选</text>
</view>
<view class="function-btn">
<view class="cancel-btn" @click="cancelBatchDelete">取消</view>
<view class="delete-btn" @click="batchDelete">删除</view>
</view>
</view>
<!-- 提示 -->
<u-toast ref="uToast" />
</view>
</template>
<script>
import HeaderBar from "@/components/HeaderBar.vue";
export default {
components: {
HeaderBar,
},
data() {
return {
activeTab: "1", // 当前激活的tab
tabList: [
{ id: "1", name: "AI咨询" },
{ id: "2", name: "人工咨询" },
],
isBatchDeleteMode: false, // 是否为批量删除模式
isMoreMenuVisible: false, // 右上角更多菜单是否可见
selectedItems: [], // 选中的项目
selectAll: false, // 是否全选
chatHistoryAI: [], // ai咨询历史记录
chatHistoryTeacher: [], // 人工咨询历史记录
};
},
computed: {
// 当前tab的历史记录
currentHistoryList() {
if (this.activeTab === "1") {
return this.chatHistoryAI;
} else {
return this.chatHistoryTeacher;
}
},
currentHistoryItems() {
const groups = this.currentHistoryList || [];
const items = [];
groups.forEach((group) => {
const conversation = (group && group.conversation) || [];
conversation.forEach((item) => items.push(item));
});
return items;
},
currentHistoryItemIds() {
return this.currentHistoryItems.map((item) => item.id);
},
},
onLoad() {
this.getChatHistoryList();
// this.GetDialogueList_User();
},
methods: {
resetBatchState() {
this.selectedItems = [];
this.selectAll = false;
this.isBatchDeleteMode = false;
},
// 获取ai历史记录
async getChatHistoryList() {
this.$u.api.GetConversationPage().then((res) => {
this.chatHistoryAI = res.data;
// if (this.chatHistoryAI.length > 0) {
// this.chatHistoryAI = res.data.map((group) => {
// // 对每个组的conversation数组进行倒序排序
// return {
// ...group,
// conversation: group.conversation.sort((a, b) => {
// // 将日期字符串转换为时间戳并比较(倒序)
// return (
// new Date(b.startTime).getTime() -
// new Date(a.startTime).getTime()
// );
// }),
// };
// });
// }
console.log("this.chatHistoryAI", this.chatHistoryAI);
});
},
// 获取人工咨询数据
async GetDialogueList_User() {
this.$u.api.GetDialogueList_UserApi().then((res) => {
this.chatHistoryTeacher = res.data;
// if (this.chatHistoryTeacher.length > 0) {
// this.chatHistoryTeacher = res.data.map((group) => {
// // 对每个组的conversation数组进行倒序排序
// return {
// ...group,
// conversation: group.conversation.sort((a, b) => {
// // 将日期字符串转换为时间戳并比较(倒序)
// return (
// new Date(b.startTime).getTime() -
// new Date(a.startTime).getTime()
// );
// }),
// };
// });
// }
});
},
// 格式化时间显示
formatTime(timestamp) {
const now = new Date();
const date = new Date(timestamp);
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const itemDate = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate()
);
// 计算时间差
const diffTime = today.getTime() - itemDate.getTime();
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
// 今天
if (diffDays === 0) {
return `${String(date.getMonth() + 1).padStart(2, "0")}/${String(
date.getDate()
).padStart(2, "0")}`;
}
// 本周内1-6天前
if (diffDays > 0 && diffDays <= 6) {
const weekdays = [
"周日",
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
];
return weekdays[date.getDay()];
}
// 今年但不是本周
if (date.getFullYear() === now.getFullYear()) {
return `${String(date.getMonth() + 1).padStart(2, "0")}/${String(
date.getDate()
).padStart(2, "0")}`;
}
// 往年
return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(
2,
"0"
)}/${String(date.getDate()).padStart(2, "0")}`;
},
handleLeftClick() {
uni.navigateBack();
},
switchTab(tab) {
if (this.activeTab === tab) return;
// 批量删除模式下切换tab时清空选中项
if (this.isBatchDeleteMode) {
this.selectedItems = [];
this.selectAll = false;
}
this.activeTab = tab;
// 切换tab时刷新当前tab的历史记录
if (tab === "1") {
this.getChatHistoryList();
} else {
this.GetDialogueList_User();
}
},
// 显示/隐藏右上角更多菜单
toggleMoreMenu() {
if (this.isBatchDeleteMode) return;
this.isMoreMenuVisible = !this.isMoreMenuVisible;
},
// 点击蒙层隐藏更多菜单
hideMoreMenu() {
this.isMoreMenuVisible = false;
},
// 取消批量删除模式
cancelBatchDelete() {
this.resetBatchState();
},
// 点击“批量删除”菜单项,进入批量删除模式
handleBatchDeleteClick() {
this.isMoreMenuVisible = false;
if (!this.isBatchDeleteMode) {
this.toggleBatchDeleteMode();
}
},
// 切换批量删除模式
toggleBatchDeleteMode() {
this.isBatchDeleteMode = !this.isBatchDeleteMode;
if (!this.isBatchDeleteMode) {
// 退出批量删除模式时清空选中项
this.selectedItems = [];
this.selectAll = false;
}
},
// 切换单个项目选中状态
toggleItemSelection(itemId) {
const index = this.selectedItems.indexOf(itemId);
if (index > -1) {
this.selectedItems.splice(index, 1);
} else {
this.selectedItems.push(itemId);
}
// 更新全选状态
this.selectAll =
this.selectedItems.length > 0 &&
this.selectedItems.length === this.currentHistoryItemIds.length;
},
// 切换全选状态
toggleSelectAll() {
const allIds = this.currentHistoryItemIds || [];
if (!allIds.length) {
this.selectAll = false;
this.selectedItems = [];
return;
}
this.selectAll = !this.selectAll;
if (this.selectAll) {
this.selectedItems = [...allIds];
} else {
this.selectedItems = [];
}
},
// 批量删除选中项
async batchDelete() {
if (this.selectedItems.length === 0) {
this.$refs.uToast.show({
title: "请选择要删除的记录",
type: "warning",
});
return;
}
const deleteIds = [...this.selectedItems];
const isAiTab = this.activeTab === "1";
try {
let res = null;
if (isAiTab) {
res = await this.$u.api.DeleteDialogueManagement({ id: deleteIds });
} else {
res = await this.$u.api.DeleteDialogueApi({ dialogueManagementIds: deleteIds });
}
if (res && res.succeed === true) {
this.resetBatchState();
if (isAiTab) {
this.getChatHistoryList();
} else {
this.GetDialogueList_User();
}
this.$refs.uToast.show({
title: "删除成功",
type: "success",
});
return;
}
this.$refs.uToast.show({
title: (res && (res.msg || res.message)) || "删除失败",
type: "error",
});
} catch (e) {
this.$refs.uToast.show({
title: "删除失败",
type: "error",
});
}
},
},
};
</script>
<style lang="scss" scoped>
.history-page {
height: 100vh;
background-color: #ffffff;
display: flex;
flex-direction: column;
position: relative;
padding-top: 88rpx;
.tab-container {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
}
.custom-tab {
padding: 0 30rpx;
margin: 24rpx 0;
display: flex;
justify-content: space-between;
align-items: center;
.tab-item {
position: relative;
padding: 12rpx 0;
margin-right: 80rpx;
cursor: pointer;
.tab-text {
font-size: 32rpx;
font-weight: 500;
color: #505866;
letter-spacing: 0.04rpx;
}
&.active .tab-text {
color: #4f6aff;
font-weight: 600;
}
.tab-underline {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
right: 0;
width: 80rpx;
height: 4rpx;
background-color: #4f6aff;
border-radius: 2rpx;
}
}
}
.more-icon-container {
width: 50rpx;
height: 50rpx;
margin-right: 30rpx;
.more-icon {
width: 50rpx;
height: 10rpx;
margin-right: 30rpx;
}
}
/* 右上角更多菜单弹层 */
.more-menu {
position: absolute;
top: 80rpx;
right: 30rpx;
z-index: 100;
background-color: #ffffff;
border: 1rpx solid rgba(79, 106, 255, 0.12);
border-radius: 24rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.08);
padding: 24rpx 28rpx;
}
.menu-card {
display: flex;
align-items: center;
gap: 6rpx;
// .menu-icon {
// color: #FF647D;
// width: 32rpx;
// height: 32rpx;
// margin-right: 12rpx;
// }
.menu-text {
font-size: 28rpx;
color: #ff647d;
letter-spacing: 2rpx;
}
}
/* 点击其它区域关闭的遮罩(透明) */
.overlay {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 99;
background: rgba(0, 0, 0, 0);
}
.content-wrapper {
padding: 30rpx;
flex: 1;
overflow-y: auto;
}
.history-list {
.date-group {
margin-bottom: 32rpx;
}
.date-header {
font-size: 26rpx;
color: #9aa0a8;
margin-bottom: 16rpx;
line-height: 1;
}
.history-item {
display: flex;
align-items: flex-start;
padding: 24rpx 0;
.item-checkbox {
margin-right: 24rpx;
padding-top: 8rpx;
cursor: pointer;
width: 48rpx;
flex: 0 0 48rpx; /* 固定宽度,避免内容因显隐而抖动 */
.checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #d9d9d9;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffffff;
&.checked {
background-color: #ff4757;
border-color: #ff4757;
.checkmark {
color: #ffffff;
font-size: 22rpx;
font-weight: bold;
}
}
}
}
.item-content {
flex: 1;
.item-header {
display: flex;
align-items: center;
margin-bottom: 30rpx;
.item-icon {
width: 50rpx;
height: 50rpx;
background-color: rgba(79, 106, 255, 0.1);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
.icon-image {
width: 26rpx;
height: 26rpx;
}
}
.item-title {
font-size: 32rpx;
font-weight: bold;
color: #333333;
flex: 1;
}
}
.item-description {
letter-spacing: 0.04rpx;
font-size: 28rpx;
color: #666666;
line-height: 1.5;
margin-bottom: 12rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
}
}
}
.batch-actions {
height: 130rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 30rpx;
border-top: 1rpx solid #eeeeee;
.select-all-container {
display: flex;
align-items: center;
cursor: pointer;
.checkbox {
width: 40rpx;
height: 40rpx;
border: 2rpx solid #d9d9d9;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffffff;
&.checked {
background-color: #ff4757;
border-color: #ff4757;
.checkmark {
color: #ffffff;
font-size: 22rpx;
font-weight: bold;
}
}
}
.select-all-text {
margin-left: 16rpx;
font-size: 28rpx;
color: #333333;
}
}
.function-btn {
display: flex;
align-items: center;
gap: 20rpx;
.cancel-btn {
background-color: #e5e3e3e4;
color: #333333;
padding: 16rpx 32rpx;
border-radius: 16rpx;
font-size: 28rpx;
cursor: pointer;
}
.delete-btn {
background-color: #ff4757;
color: #ffffff;
padding: 16rpx 32rpx;
border-radius: 16rpx;
font-size: 28rpx;
cursor: pointer;
}
}
}
}
</style>