Files
ss-tiku-manage-h5/src/pages/account/log.vue
2026-01-30 14:08:23 +08:00

586 lines
12 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="log-manage-container">
<!-- 页面标题 -->
<view class="page-header">
<view class="header-left" @click="goBack">
<view class="back-icon"></view>
</view>
<view class="header-title">操作日志查看</view>
<view class="header-right" @click="exportLog">
<view class="export-btn">导出</view>
</view>
</view>
<!-- 筛选条件 -->
<view class="filter-section">
<view class="filter-row">
<view class="filter-item">
<view class="filter-label">操作类型</view>
<view class="filter-control">
<picker
:range="operationOptions"
:value="operationIndex"
@change="onOperationChange"
class="picker"
>
<view class="picker-text">{{ operationOptions[operationIndex] }}</view>
</picker>
</view>
</view>
<view class="filter-item">
<view class="filter-label">时间范围</view>
<view class="filter-control">
<picker
mode="date"
start="2026-01-01"
end="2026-12-31"
:value="dateRange"
@change="onDateChange"
class="picker"
>
<view class="picker-text">{{ dateRangeDisplay }}</view>
</picker>
</view>
</view>
<view class="filter-item">
<view class="filter-label">搜索</view>
<view class="filter-control">
<input
v-model="searchKeyword"
class="search-input"
placeholder="请输入操作人或账号"
@input="onSearch"
/>
</view>
</view>
</view>
</view>
<!-- 日志列表 -->
<view class="log-list">
<view
v-for="(log, index) in logList"
:key="index"
class="log-item"
>
<view class="log-header">
<view class="log-time">{{ log.time }}</view>
<view class="log-status" :class="log.statusClass">{{ log.status }}</view>
</view>
<view class="log-content">
<view class="log-operation">{{ log.operation }}</view>
<view class="log-detail">{{ log.detail }}</view>
</view>
<view class="log-meta">
<view class="log-operator">{{ log.operator }}</view>
<view class="log-ip">{{ log.ip }}</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="logList.length === 0" class="empty-state">
<view class="empty-icon">📋</view>
<view class="empty-text">暂无操作日志</view>
</view>
<!-- 分页 -->
<view v-if="logList.length > 0" class="pagination">
<view class="page-info">
{{ totalLogs }} 当前第 {{ currentPage }}
</view>
<view class="page-controls">
<view
class="page-btn"
:class="{ disabled: currentPage === 1 }"
@click="goToPage(currentPage - 1)"
>
上一页
</view>
<view
class="page-btn"
:class="{ disabled: currentPage === totalPages }"
@click="goToPage(currentPage + 1)"
>
下一页
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from "vue"
// 操作类型选项
const operationOptions = ['全部', '账号创建', '账号冻结', '账号启用', '密码修改', '权限变更']
const operationIndex = ref(0)
// 日期范围
const dateRange = ref('2026-01-29')
const dateRangeDisplay = ref('2026-01-29')
// 搜索关键词
const searchKeyword = ref('')
// 日志列表
const logList = ref([
{
id: 1,
time: '2026-01-29 15:30:45',
operation: '账号创建',
detail: '创建了新的分销员账号:张教练',
operator: '系统管理员',
ip: '192.168.1.100',
status: '成功',
statusClass: 'status-success'
},
{
id: 2,
time: '2026-01-29 14:20:30',
operation: '账号冻结',
detail: '冻结了分销员账号:王教练',
operator: '系统管理员',
ip: '192.168.1.100',
status: '成功',
statusClass: 'status-success'
},
{
id: 3,
time: '2026-01-29 10:15:20',
operation: '密码修改',
detail: '修改了账号密码:李教练',
operator: '李教练',
ip: '192.168.1.101',
status: '成功',
statusClass: 'status-success'
},
{
id: 4,
time: '2026-01-28 16:45:10',
operation: '权限变更',
detail: '修改了分销员权限:张教练',
operator: '系统管理员',
ip: '192.168.1.100',
status: '成功',
statusClass: 'status-success'
},
{
id: 5,
time: '2026-01-28 09:30:00',
operation: '账号创建',
detail: '创建了新的分销员账号:刘教练',
operator: '系统管理员',
ip: '192.168.1.100',
status: '成功',
statusClass: 'status-success'
}
])
// 分页信息
const currentPage = ref(1)
const totalLogs = ref(100)
const pageSize = ref(10)
// 计算总页数
const totalPages = computed(() => {
return Math.ceil(totalLogs.value / pageSize.value)
})
onMounted(() => {
// 实际项目中应从接口获取操作日志
// loadLogList()
})
// 返回上一页
function goBack() {
uni.navigateBack({ delta: 1 })
}
// 导出日志
function exportLog() {
uni.showModal({
title: '导出日志',
content: '确定要导出当前筛选条件的操作日志吗?',
success: function(res) {
if (res.confirm) {
uni.showLoading({ title: '导出中...' })
setTimeout(() => {
uni.hideLoading()
uni.showToast({
title: '导出成功',
icon: 'success'
})
// 实际项目中应调用接口导出日志
// exportLogData()
}, 1500)
}
}
})
}
// 操作类型变更
function onOperationChange(e) {
const value = e.detail.value
operationIndex.value = value
// 实际项目中应根据操作类型筛选日志
// filterLogList()
}
// 日期变更
function onDateChange(e) {
dateRange.value = e.detail.value
dateRangeDisplay.value = e.detail.value
// 实际项目中应根据日期筛选日志
// filterLogList()
}
// 搜索
function onSearch() {
// 实际项目中应根据关键词搜索日志
// searchLogList()
}
// 跳转到指定页码
function goToPage(page) {
if (page < 1 || page > totalPages.value) {
return
}
currentPage.value = page
// 实际项目中应加载指定页码的日志
// loadLogList(page)
}
</script>
<style lang="scss" scoped>
/* #ifndef APP-NVUE */
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #f5f7fa;
min-height: 100%;
height: auto;
}
view {
font-size: 14px;
line-height: inherit;
}
/* #endif */
.log-manage-container {
flex: 1;
display: flex;
flex-direction: column;
}
/* 页面头部 */
.page-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 120rpx;
background-color: #fff;
padding: 0 32rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.header-left {
width: 60rpx;
}
.back-icon {
font-size: 40rpx;
color: #303133;
cursor: pointer;
}
.header-title {
font-size: 32rpx;
font-weight: bold;
color: #303133;
}
.header-right {
width: 60rpx;
text-align: right;
}
.export-btn {
font-size: 28rpx;
color: #409eff;
font-weight: 600;
cursor: pointer;
}
/* 筛选条件 */
.filter-section {
padding: 24rpx 32rpx;
background-color: #fff;
margin: 16rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.filter-row {
display: flex;
gap: 16rpx;
flex-wrap: wrap;
}
.filter-item {
flex: 1;
min-width: 200rpx;
}
.filter-label {
font-size: 24rpx;
color: #606266;
margin-bottom: 8rpx;
}
.filter-control {
background-color: #f9f9f9;
border: 1rpx solid #dcdfe6;
border-radius: 8rpx;
padding: 16rpx;
}
.picker {
display: flex;
justify-content: space-between;
align-items: center;
}
.picker-text {
font-size: 24rpx;
color: #303133;
}
.search-input {
font-size: 24rpx;
color: #303133;
width: 100%;
}
/* 日志列表 */
.log-list {
flex: 1;
padding: 0 16rpx;
}
.log-item {
background-color: #fff;
border-radius: 16rpx;
padding: 24rpx;
margin-bottom: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.log-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
}
.log-time {
font-size: 20rpx;
color: #606266;
}
.log-status {
font-size: 20rpx;
font-weight: 600;
padding: 4rpx 12rpx;
border-radius: 12rpx;
}
.status-success {
color: #67c23a;
background-color: rgba(103, 194, 58, 0.1);
}
.status-fail {
color: #f56c6c;
background-color: rgba(245, 108, 108, 0.1);
}
.log-content {
margin-bottom: 16rpx;
}
.log-operation {
font-size: 24rpx;
font-weight: 600;
color: #303133;
margin-bottom: 8rpx;
}
.log-detail {
font-size: 20rpx;
color: #606266;
line-height: 1.4;
}
.log-meta {
display: flex;
justify-content: space-between;
font-size: 20rpx;
color: #909399;
}
/* 空状态 */
.empty-state {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
}
.empty-icon {
font-size: 80rpx;
margin-bottom: 24rpx;
}
.empty-text {
font-size: 24rpx;
color: #909399;
}
/* 分页 */
.pagination {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx 32rpx;
background-color: #fff;
margin: 16rpx;
border-radius: 16rpx;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
}
.page-info {
font-size: 20rpx;
color: #606266;
}
.page-controls {
display: flex;
gap: 16rpx;
}
.page-btn {
padding: 8rpx 16rpx;
border-radius: 8rpx;
font-size: 20rpx;
font-weight: 600;
color: #409eff;
cursor: pointer;
}
.page-btn.disabled {
color: #909399;
cursor: not-allowed;
}
/* 平板和大屏响应式 */
@media screen and (min-width: 768px) {
.log-manage-container {
max-width: 1000px;
margin: 0 auto;
width: 100%;
}
.filter-section,
.pagination {
margin: 0 32rpx 24rpx;
padding: 32rpx;
}
.log-list {
padding: 0 32rpx;
}
.log-item {
margin-bottom: 24rpx;
padding: 32rpx;
}
.filter-row {
gap: 32rpx;
}
.filter-item {
min-width: 250rpx;
}
.filter-label {
font-size: 26rpx;
}
.picker-text,
.search-input {
font-size: 26rpx;
}
.filter-control {
padding: 20rpx;
}
.log-time,
.log-detail,
.log-meta,
.page-info {
font-size: 22rpx;
}
.log-status {
font-size: 22rpx;
padding: 6rpx 16rpx;
}
.log-operation {
font-size: 28rpx;
}
.page-btn {
font-size: 22rpx;
padding: 12rpx 24rpx;
}
}
/* 大屏设备响应式 */
@media screen and (min-width: 1024px) {
.log-manage-container {
max-width: 1200px;
}
.filter-item {
min-width: 300rpx;
}
.filter-label {
font-size: 28rpx;
}
.picker-text,
.search-input {
font-size: 28rpx;
}
.log-operation {
font-size: 30rpx;
}
.log-time,
.log-detail,
.log-meta {
font-size: 24rpx;
}
}
</style>