Files
2025-10-22 08:19:00 +08:00

308 lines
10 KiB
Vue

<template>
<view class="operation-logs">
<!-- 顶部导航栏 -->
<view class="nav-bar">
<view class="nav-back" @click="navigateBack">
<u-icon name="arrow-left" size="24" color="#606266"></u-icon>
</view>
<view class="nav-title">操作日志</view>
<view class="nav-right">
<u-button type="text" @click="filterLogs">筛选</u-button>
</view>
</view>
<!-- 搜索框 -->
<view class="search-box">
<u-search placeholder="搜索操作人/操作内容" v-model="searchKeyword"></u-search>
</view>
<!-- 时间范围选择 -->
<view class="time-range">
<u-cell-group>
<u-cell
title="时间范围"
:right-text="`${startDate} ${endDate}`"
is-link
@click="showDateRangeModal = true"
></u-cell>
</u-cell-group>
</view>
<!-- 操作日志列表 -->
<view class="logs-list">
<u-list v-if="filteredLogs.length > 0" :load-more="loadMore" @loadmore="onLoadMore">
<u-list-item v-for="log in paginatedLogs" :key="log.id" :border="true">
<view class="log-item">
<view class="log-header">
<view class="log-user">{{ log.userName }}</view>
<view class="log-time">{{ formatTime(log.timestamp) }}</view>
</view>
<view class="log-content">{{ log.content }}</view>
<view class="log-result">
<u-tag :type="log.success ? 'success' : 'error'">
{{ log.success ? '成功' : '失败' }}
</u-tag>
</view>
</view>
</u-list-item>
</u-list>
<u-empty v-else text="暂无操作日志"></u-empty>
</view>
<!-- 时间范围选择弹窗 -->
<u-popup v-model="showDateRangeModal" mode="bottom" :round="true" :closeable="true">
<view class="modal-content">
<view class="modal-title">选择时间范围</view>
<view class="date-picker">
<u-datetime-picker
v-model="startDateTime"
mode="date"
:formatter="formatter"
@confirm="onStartDateConfirm"
></u-datetime-picker>
<view class="date-separator"></view>
<u-datetime-picker
v-model="endDateTime"
mode="date"
:formatter="formatter"
@confirm="onEndDateConfirm"
></u-datetime-picker>
</view>
<view class="modal-buttons">
<u-button @click="showDateRangeModal = false" style="flex: 1; margin-right: 20rpx;">取消</u-button>
<u-button type="primary" @click="confirmDateRange" style="flex: 1;">确定</u-button>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data() {
return {
searchKeyword: '',
startDate: '2023-01-01',
endDate: '2023-12-31',
startDateTime: [2023, 0, 1],
endDateTime: [2023, 11, 31],
showDateRangeModal: false,
currentPage: 1,
pageSize: 20,
loadMore: {
loading: false,
finished: false,
error: false
},
logs: [
{ id: 1, userName: '张三', content: '添加新用户:李四', timestamp: 1691234567890, success: true },
{ id: 2, userName: '李四', content: '创建新部门:市场部', timestamp: 1691234567891, success: true },
{ id: 3, userName: '王五', content: '上传图片:项目截图.jpg', timestamp: 1691234567892, success: true },
{ id: 4, userName: '张三', content: '审核图片:项目截图.jpg', timestamp: 1691234567893, success: true },
{ id: 5, userName: '孙八', content: '修改用户角色:李四 - 部门负责人', timestamp: 1691234567894, success: true },
{ id: 6, userName: '张三', content: '删除过期图片', timestamp: 1691234567895, success: false },
{ id: 7, userName: '李四', content: '创建收集任务:季度报告图片', timestamp: 1691234567896, success: true },
{ id: 8, userName: '王五', content: '登录系统', timestamp: 1691234567897, success: true },
{ id: 9, userName: '张三', content: '修改系统设置:最大上传图片大小', timestamp: 1691234567898, success: true },
{ id: 10, userName: '李四', content: '批量审核图片', timestamp: 1691234567899, success: true },
{ id: 11, userName: '王五', content: '查看任务统计报表', timestamp: 1691234567900, success: true },
{ id: 12, userName: '张三', content: '系统数据备份', timestamp: 1691234567901, success: true },
{ id: 13, userName: '李四', content: '修改部门负责人:技术部', timestamp: 1691234567902, success: true },
{ id: 14, userName: '王五', content: '上传图片:活动照片.png', timestamp: 1691234567903, success: true },
{ id: 15, userName: '张三', content: '修改用户密码:王五', timestamp: 1691234567904, success: false },
{ id: 16, userName: '李四', content: '查看用户列表', timestamp: 1691234567905, success: true },
{ id: 17, userName: '王五', content: '修改任务截止时间', timestamp: 1691234567906, success: true },
{ id: 18, userName: '张三', content: '清理系统缓存', timestamp: 1691234567907, success: true },
{ id: 19, userName: '李四', content: '上传图片:产品展示.jpg', timestamp: 1691234567908, success: true },
{ id: 20, userName: '王五', content: '退出系统', timestamp: 1691234567909, success: true },
{ id: 21, userName: '张三', content: '修改用户信息:李四', timestamp: 1691234567910, success: true },
{ id: 22, userName: '李四', content: '删除部门:测试部', timestamp: 1691234567911, success: true }
]
}
},
computed: {
filteredLogs() {
let result = this.logs
// 按关键词搜索
if (this.searchKeyword) {
result = result.filter(log =>
log.userName.includes(this.searchKeyword) ||
log.content.includes(this.searchKeyword)
)
}
// 按时间范围过滤
const startTimestamp = new Date(this.startDate).getTime()
const endTimestamp = new Date(this.endDate).setHours(23, 59, 59, 999)
result = result.filter(log =>
log.timestamp >= startTimestamp && log.timestamp <= endTimestamp
)
// 按时间倒序排列
return result.sort((a, b) => b.timestamp - a.timestamp)
},
paginatedLogs() {
const start = (this.currentPage - 1) * this.pageSize
const end = start + this.pageSize
return this.filteredLogs.slice(start, end)
}
},
methods: {
navigateBack() {
uni.navigateBack()
},
formatTime(timestamp) {
const date = new Date(timestamp)
const year = date.getFullYear()
const month = (date.getMonth() + 1).toString().padStart(2, '0')
const day = date.getDate().toString().padStart(2, '0')
const hour = date.getHours().toString().padStart(2, '0')
const minute = date.getMinutes().toString().padStart(2, '0')
const second = date.getSeconds().toString().padStart(2, '0')
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
},
formatter(type, value) {
if (type === 'year') {
return `${value}年`
} else if (type === 'month') {
return `${value}月`
} else if (type === 'day') {
return `${value}日`
}
return value
},
onStartDateConfirm(e) {
const [year, month, day] = e
this.startDate = `${year}-${(month + 1).toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
},
onEndDateConfirm(e) {
const [year, month, day] = e
this.endDate = `${year}-${(month + 1).toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`
},
confirmDateRange() {
this.showDateRangeModal = false
this.currentPage = 1
this.updateLoadMoreStatus()
},
filterLogs() {
// 筛选功能可以进一步扩展
uni.showToast({ title: '筛选功能开发中', icon: 'none' })
},
onLoadMore() {
if (this.loadMore.loading) return
this.loadMore.loading = true
// 模拟加载更多数据
setTimeout(() => {
this.currentPage++
this.loadMore.loading = false
this.updateLoadMoreStatus()
}, 1000)
},
updateLoadMoreStatus() {
const hasMore = this.paginatedLogs.length < this.filteredLogs.length
this.loadMore.finished = !hasMore
}
}
}
</script>
<style lang="scss">
.operation-logs {
padding-bottom: 20rpx;
background-color: #f5f5f5;
.nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
height: 88rpx;
padding: 0 30rpx;
background-color: #fff;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
.nav-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
}
.search-box {
padding: 20rpx;
background-color: #fff;
}
.time-range {
margin-top: 20rpx;
padding: 0 20rpx;
}
.logs-list {
margin-top: 20rpx;
background-color: #fff;
.log-item {
padding: 20rpx;
.log-header {
display: flex;
justify-content: space-between;
margin-bottom: 10rpx;
.log-user {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.log-time {
font-size: 28rpx;
color: #999;
}
}
.log-content {
font-size: 30rpx;
color: #666;
margin-bottom: 10rpx;
line-height: 1.5;
}
.log-result {
display: flex;
justify-content: flex-end;
}
}
}
.modal-content {
padding: 30rpx;
.modal-title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
color: #333;
}
.date-picker {
margin-bottom: 30rpx;
.date-separator {
text-align: center;
padding: 20rpx 0;
font-size: 32rpx;
color: #666;
}
}
.modal-buttons {
display: flex;
}
}
}
</style>