feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<Card class="search-history-panel">
|
||||
<view class="panel-header">
|
||||
<Typography variant="h4" weight="semibold">搜索历史</Typography>
|
||||
<Button size="small" type="text" @click="handleClearHistory">
|
||||
<Typography variant="caption" color="rgba(196, 30, 58, 255)">清除历史</Typography>
|
||||
</Button>
|
||||
</view>
|
||||
|
||||
<view v-if="history.length === 0" class="empty-history">
|
||||
<EmptyState
|
||||
icon="empty"
|
||||
title="暂无搜索历史"
|
||||
description="执行搜索后,搜索条件将显示在这里"
|
||||
size="small"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view v-else class="history-list">
|
||||
<view
|
||||
v-for="item in history"
|
||||
:key="item.id"
|
||||
class="history-item"
|
||||
@click="handleSelectHistory(item)"
|
||||
>
|
||||
<view class="history-content">
|
||||
<Typography variant="body" class="history-title">
|
||||
{{ formatHistoryTitle(item.condition) }}
|
||||
</Typography>
|
||||
<Typography variant="caption" class="history-time">
|
||||
{{ formatTime(item.createdAt) }}
|
||||
</Typography>
|
||||
</view>
|
||||
<Icon name="right" size="16rpx" color="rgba(113, 113, 122, 255)" />
|
||||
</view>
|
||||
</view>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import type { SearchRequest } from '../../types/search'
|
||||
import searchService from '../../services/searchService'
|
||||
import Card from '../Card/Card.vue'
|
||||
import Button from '../Button/Button.vue'
|
||||
import Typography from '../Typography/Typography.vue'
|
||||
import Icon from '../Icon/Icon.vue'
|
||||
import EmptyState from '../EmptyState/index.vue'
|
||||
|
||||
interface HistoryItem {
|
||||
id: string
|
||||
condition: SearchRequest
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
const emit = defineEmits<{
|
||||
select: [condition: SearchRequest]
|
||||
}>()
|
||||
|
||||
const history = ref<HistoryItem[]>([])
|
||||
|
||||
onMounted(() => {
|
||||
loadHistory()
|
||||
})
|
||||
|
||||
function loadHistory() {
|
||||
history.value = searchService.getSearchHistory()
|
||||
}
|
||||
|
||||
function handleSelectHistory(item: HistoryItem) {
|
||||
emit('select', item.condition)
|
||||
}
|
||||
|
||||
function handleClearHistory() {
|
||||
uni.showModal({
|
||||
title: '确认清除',
|
||||
content: '确定要清除所有搜索历史吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
searchService.clearSearchHistory()
|
||||
history.value = []
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function formatHistoryTitle(condition: SearchRequest): string {
|
||||
const conditionCount = condition.conditions.length
|
||||
const days = condition.days
|
||||
|
||||
let title = `${conditionCount}个条件,${days}天范围`
|
||||
|
||||
if (conditionCount > 0) {
|
||||
const firstCondition = condition.conditions[0]
|
||||
const type = firstCondition.type === 'suitable' ? '宜' : '忌'
|
||||
const items = firstCondition.items.slice(0, 2).join('、')
|
||||
|
||||
title += `(${type}${items}${firstCondition.items.length > 2 ? '...' : ''})`
|
||||
}
|
||||
|
||||
return title
|
||||
}
|
||||
|
||||
function formatTime(timeStr: string): string {
|
||||
const date = new Date(timeStr)
|
||||
const now = new Date()
|
||||
const diffMs = now.getTime() - date.getTime()
|
||||
const diffHours = Math.floor(diffMs / (1000 * 60 * 60))
|
||||
|
||||
if (diffHours < 1) {
|
||||
return '刚刚'
|
||||
} else if (diffHours < 24) {
|
||||
return `${diffHours}小时前`
|
||||
} else {
|
||||
const diffDays = Math.floor(diffHours / 24)
|
||||
if (diffDays < 7) {
|
||||
return `${diffDays}天前`
|
||||
} else {
|
||||
return date.toLocaleDateString()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.search-history-panel {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.empty-history {
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
.history-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.history-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
background: rgba(244, 244, 245, 255);
|
||||
border-radius: var(--radius-md);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
|
||||
&:active {
|
||||
background: rgba(230, 225, 220, 255);
|
||||
}
|
||||
}
|
||||
|
||||
.history-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.history-title {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.history-time {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user