308 lines
10 KiB
Vue
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> |