Files
cunkebao_v3/Cunkebao/pages/content/index.vue

741 lines
18 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="content-container">
<!-- 顶部导航栏 -->
<view class="header">
<view class="back-icon" @click="goBack">
<u-icon name="arrow-left" size="42" color="black"></u-icon>
</view>
<view class="title">内容库</view>
<view class="header-right">
<view class="add-btn" @click="createContent">
<text class="add-icon">+</text>
<text class="add-text">新建</text>
</view>
</view>
</view>
<!-- 内容区 -->
<view class="content-wrapper">
<!-- 搜索框 -->
<view class="search-box">
<u-search
v-model="searchKeyword"
placeholder="搜索内容库..."
:showAction="false"
shape="round"
:clearabled="true"
height="70"
bgColor="#f4f4f4"
></u-search>
<view class="filter-btn" @click="showFilter">
<u-icon name="filter" size="36" color="#000"></u-icon>
</view>
<view class="refresh-btn" @click="refreshData">
<u-icon name="reload" size="36" color="#000"></u-icon>
</view>
</view>
<!-- 标签页 -->
<view class="tabs">
<view
class="tab-item"
:class="{ active: currentTab === 'all' }"
@click="switchTab('all')"
>
全部
</view>
<view
class="tab-item"
:class="{ active: currentTab === 'friends' }"
@click="switchTab('friends')"
>
微信好友
</view>
<view
class="tab-item"
:class="{ active: currentTab === 'groups' }"
@click="switchTab('groups')"
>
聊天群
</view>
</view>
<!-- 内容列表 -->
<view class="content-list" v-if="filteredContents.length > 0">
<view class="content-item" v-for="(item, index) in filteredContents" :key="index">
<view class="content-header">
<text class="content-title">{{item.title}}</text>
<view class="usage-tag" :class="item.used ? 'used' : 'unused'">
{{item.used ? '已使用' : '未使用'}}
</view>
<view class="more-icon" @click.stop="showOptions(item)">
<u-icon name="more-dot-fill" size="32" color="#333"></u-icon>
</view>
</view>
<view class="content-info">
<view class="info-row">
<text class="info-label">来源</text>
<view class="source-avatars">
<image v-for="(avatar, i) in item.sourceAvatars" :key="i" :src="avatar" mode="aspectFill" class="source-avatar"></image>
</view>
</view>
<view class="info-row">
<text class="info-label">创建人</text>
<text class="info-value">{{item.creator}}</text>
</view>
<view class="info-row">
<text class="info-label">内容数量</text>
<text class="info-value">{{item.contentCount}}</text>
</view>
<view class="info-row">
<text class="info-label">更新时间</text>
<text class="info-value">{{item.updateTime}}</text>
</view>
</view>
</view>
</view>
<!-- 加载中提示 -->
<view class="loading-container" v-else-if="loading">
<text class="loading-text">加载中...</text>
</view>
<!-- 空状态 -->
<view class="empty-container" v-else>
<image src="/static/images/empty.png" mode="aspectFit" class="empty-img"></image>
<text class="empty-text">暂无内容</text>
</view>
</view>
<!-- 底部导航栏 -->
<CustomTabBar active="work"></CustomTabBar>
<!-- 筛选弹窗 -->
<u-popup :show="showFilterPopup" @close="closeFilterPopup" mode="bottom">
<view class="popup-content">
<view class="popup-header">
<text class="popup-title">筛选条件</text>
<view class="popup-close" @click="closeFilterPopup">
<u-icon name="close" size="28" color="#999"></u-icon>
</view>
</view>
<view class="popup-body">
<view class="filter-section">
<view class="filter-title">使用状态</view>
<view class="filter-options">
<view
class="filter-option"
:class="{ active: selectedUsage === 'all' }"
@click="selectUsage('all')"
>
全部
</view>
<view
class="filter-option"
:class="{ active: selectedUsage === 'used' }"
@click="selectUsage('used')"
>
已使用
</view>
<view
class="filter-option"
:class="{ active: selectedUsage === 'unused' }"
@click="selectUsage('unused')"
>
未使用
</view>
</view>
</view>
<view class="filter-section">
<view class="filter-title">更新时间</view>
<view class="filter-options">
<view
class="filter-option"
:class="{ active: selectedTime === 'all' }"
@click="selectTime('all')"
>
全部时间
</view>
<view
class="filter-option"
:class="{ active: selectedTime === 'today' }"
@click="selectTime('today')"
>
今天
</view>
<view
class="filter-option"
:class="{ active: selectedTime === 'week' }"
@click="selectTime('week')"
>
本周
</view>
<view
class="filter-option"
:class="{ active: selectedTime === 'month' }"
@click="selectTime('month')"
>
本月
</view>
</view>
</view>
<view class="filter-buttons">
<view class="reset-btn" @click="resetFilter">重置</view>
<view class="confirm-btn" @click="applyFilter">确定</view>
</view>
</view>
</view>
</u-popup>
<!-- 内容操作弹窗 -->
<u-popup :show="showActionPopup" @close="closeActionPopup" mode="bottom">
<view class="action-list">
<view class="action-item" @click="editContent">
<u-icon name="edit-pen" size="32" color="#333"></u-icon>
<text>编辑内容</text>
</view>
<view class="action-item" @click="shareContent">
<u-icon name="share" size="32" color="#333"></u-icon>
<text>分享内容</text>
</view>
<view class="action-item delete" @click="deleteContent">
<u-icon name="trash" size="32" color="#fa5151"></u-icon>
<text>删除内容</text>
</view>
<view class="action-item cancel" @click="closeActionPopup">
<text>取消</text>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import CustomTabBar from '@/components/CustomTabBar.vue'
export default {
components: {
CustomTabBar
},
data() {
return {
searchKeyword: '',
currentTab: 'all',
showFilterPopup: false,
showActionPopup: false,
selectedUsage: 'all',
selectedTime: 'all',
tempSelectedUsage: 'all',
tempSelectedTime: 'all',
loading: true,
currentContent: null,
contents: [
{
id: 1,
title: '微信好友广告',
used: true,
sourceAvatars: ['/static/images/avatar.png'],
creator: '海尼',
contentCount: 0,
updateTime: '2024-02-09 12:30'
},
{
id: 2,
title: '开发群',
used: true,
sourceAvatars: ['/static/images/avatar.png'],
creator: 'karuo',
contentCount: 0,
updateTime: '2024-02-09 12:30'
}
]
}
},
computed: {
filteredContents() {
let result = [...this.contents];
// 搜索关键词筛选
if (this.searchKeyword) {
result = result.filter(item =>
item.title.includes(this.searchKeyword) ||
item.creator.includes(this.searchKeyword)
);
}
// 标签页筛选
if (this.currentTab === 'friends') {
result = result.filter(item => item.title.includes('好友'));
} else if (this.currentTab === 'groups') {
result = result.filter(item => item.title.includes('群'));
}
// 使用状态筛选
if (this.selectedUsage === 'used') {
result = result.filter(item => item.used);
} else if (this.selectedUsage === 'unused') {
result = result.filter(item => !item.used);
}
// 时间筛选
if (this.selectedTime !== 'all') {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
const weekAgo = today - 7 * 24 * 60 * 60 * 1000;
const monthAgo = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate()).getTime();
result = result.filter(item => {
const itemTime = new Date(item.updateTime).getTime();
if (this.selectedTime === 'today') {
return itemTime >= today;
} else if (this.selectedTime === 'week') {
return itemTime >= weekAgo;
} else if (this.selectedTime === 'month') {
return itemTime >= monthAgo;
}
return true;
});
}
return result;
}
},
onLoad() {
this.loadData();
},
methods: {
// 返回上一页
goBack() {
uni.navigateBack();
},
// 刷新数据
refreshData() {
this.loading = true;
setTimeout(() => {
this.loading = false;
uni.showToast({
title: '刷新成功',
icon: 'none'
});
}, 1000);
},
// 显示筛选弹窗
showFilter() {
this.tempSelectedUsage = this.selectedUsage;
this.tempSelectedTime = this.selectedTime;
this.showFilterPopup = true;
},
// 关闭筛选弹窗
closeFilterPopup() {
this.showFilterPopup = false;
},
// 切换标签页
switchTab(tab) {
this.currentTab = tab;
},
// 选择使用状态
selectUsage(usage) {
this.tempSelectedUsage = usage;
},
// 选择时间范围
selectTime(time) {
this.tempSelectedTime = time;
},
// 重置筛选条件
resetFilter() {
this.tempSelectedUsage = 'all';
this.tempSelectedTime = 'all';
},
// 应用筛选条件
applyFilter() {
this.selectedUsage = this.tempSelectedUsage;
this.selectedTime = this.tempSelectedTime;
this.closeFilterPopup();
},
// 显示内容操作弹窗
showOptions(content) {
this.currentContent = content;
this.showActionPopup = true;
},
// 关闭内容操作弹窗
closeActionPopup() {
this.showActionPopup = false;
},
// 创建内容
createContent() {
uni.navigateTo({
url: '/pages/content/detail'
});
},
// 编辑内容
editContent() {
uni.showToast({
title: `编辑内容:${this.currentContent.title}`,
icon: 'none'
});
this.closeActionPopup();
},
// 分享内容
shareContent() {
uni.showToast({
title: `分享内容:${this.currentContent.title}`,
icon: 'none'
});
this.closeActionPopup();
},
// 删除内容
deleteContent() {
uni.showModal({
title: '提示',
content: `确定要删除内容"${this.currentContent.title}"吗?`,
success: (res) => {
if (res.confirm) {
this.contents = this.contents.filter(item => item.id !== this.currentContent.id);
uni.showToast({
title: '删除成功',
icon: 'success'
});
}
this.closeActionPopup();
}
});
},
// 加载数据
loadData() {
this.loading = true;
setTimeout(() => {
this.loading = false;
}, 1000);
}
}
}
</script>
<style lang="scss" scoped>
.content-container {
min-height: 100vh;
background-color: #f9fafb;
padding-bottom: 150rpx; /* 为底部导航栏预留空间 */
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 25rpx 30rpx;
background-color: #fff;
border-bottom: 1px solid #f0f0f0;
.back-icon {
width: 60rpx;
color: #000;
padding: 10rpx;
border-radius: 50%;
&:active {
background-color: rgba(0, 0, 0, 0.05);
}
}
.title {
font-size: 38rpx;
font-weight: 600;
margin-left: -60rpx; /* 使标题居中 */
flex: 1;
text-align: center;
}
.header-right {
.add-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #4080ff;
border-radius: 30rpx;
padding: 12rpx 24rpx;
color: #fff;
.add-icon {
font-size: 36rpx;
font-weight: bold;
margin-right: 6rpx;
line-height: 1;
}
.add-text {
font-size: 28rpx;
}
}
}
}
.content-wrapper {
padding: 20rpx 0;
}
.search-box {
display: flex;
align-items: center;
padding: 0 30rpx 20rpx;
.u-search {
flex: 1;
}
.filter-btn, .refresh-btn {
margin-left: 20rpx;
padding: 10rpx;
}
}
.tabs {
display: flex;
margin: 0 30rpx 20rpx;
background-color: #fff;
border-radius: 16rpx;
overflow: hidden;
.tab-item {
flex: 1;
text-align: center;
padding: 24rpx 0;
font-size: 28rpx;
color: #666;
&.active {
color: #4080ff;
font-weight: 500;
position: relative;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 40rpx;
height: 4rpx;
background-color: #4080ff;
border-radius: 2rpx;
}
}
}
}
.content-list {
padding: 0 30rpx;
.content-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
.content-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.content-title {
font-size: 32rpx;
font-weight: 500;
color: #333;
flex: 1;
}
.usage-tag {
font-size: 24rpx;
padding: 4rpx 12rpx;
border-radius: 8rpx;
margin-right: 16rpx;
&.used {
background-color: #e6f7ff;
color: #1890ff;
}
&.unused {
background-color: #f6ffed;
color: #52c41a;
}
}
.more-icon {
padding: 10rpx;
}
}
.content-info {
.info-row {
display: flex;
align-items: center;
margin-bottom: 10rpx;
font-size: 28rpx;
color: #666;
.info-label {
color: #999;
min-width: 150rpx;
}
.source-avatars {
display: flex;
.source-avatar {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
margin-right: 10rpx;
}
}
}
}
}
}
.loading-container, .empty-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 300rpx;
.loading-text, .empty-text {
font-size: 30rpx;
color: #999;
margin-top: 20rpx;
}
.empty-img {
width: 200rpx;
height: 200rpx;
}
}
.popup-content {
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
.popup-title {
font-size: 32rpx;
font-weight: 500;
}
.popup-close {
padding: 10rpx;
}
}
.popup-body {
padding: 30rpx;
.filter-section {
margin-bottom: 30rpx;
.filter-title {
font-size: 30rpx;
font-weight: 500;
color: #333;
margin-bottom: 20rpx;
}
.filter-options {
display: flex;
flex-wrap: wrap;
.filter-option {
padding: 16rpx 30rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #666;
margin-right: 20rpx;
margin-bottom: 20rpx;
&.active {
background-color: #e6f7ff;
color: #4080ff;
font-weight: 500;
}
}
}
}
.filter-buttons {
display: flex;
margin-top: 40rpx;
.reset-btn, .confirm-btn {
flex: 1;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
border-radius: 8rpx;
}
.reset-btn {
background-color: #f5f5f5;
color: #666;
margin-right: 20rpx;
}
.confirm-btn {
background-color: #4080ff;
color: #fff;
}
}
}
}
.action-list {
background-color: #fff;
border-top-left-radius: 16rpx;
border-top-right-radius: 16rpx;
.action-item {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
font-size: 32rpx;
color: #333;
border-bottom: 1px solid #f5f5f5;
u-icon {
margin-right: 15rpx;
}
&.delete {
color: #fa5151;
}
&.cancel {
color: #666;
margin-top: 16rpx;
border-bottom: none;
}
}
}
</style>