28 KiB
28 KiB
首页统计数据接口 - 前端对接文档
📋 目录
接口概述
基本信息
| 项目 | 内容 |
|---|---|
| 接口名称 | 获取首页统计数据 |
| 接口路径 | /admin/statistics/home-data |
| 请求方法 | GET |
| 需要认证 | ✅ 是(需要JWT Token) |
| 权限要求 | 所有登录用户可访问 |
| 版本 | v3 |
功能说明
获取首页展示的统计数据,包括:
- ✅ 今日待审核文件数
- ✅ 当前周期已审核文件数
- ✅ 审核文件同比增长
- ✅ 当前周期审核通过率
- ✅ 通过率同比增长
- ✅ 检测到的问题总数
- ✅ 问题数量同比增长
核心特性
-
三级权限隔离
- 省级管理员:查看全省数据
- 地市管理员:查看本地市数据
- 普通用户:只能查看自己的数据
-
灵活时间范围
- 支持今天、近3天、近7天、近30天、本月
- 自动对比上一个相同周期
-
类型筛选
- 支持按文档类型ID筛选
- 支持多个类型ID组合
-
性能优化
- Redis缓存20分钟
- 响应时间 < 200ms
快速开始
最简单的调用
// 获取本月统计数据(默认)
fetch('/admin/statistics/home-data', {
headers: {
'Authorization': 'Bearer YOUR_JWT_TOKEN'
}
})
.then(res => res.json())
.then(data => console.log(data));
Vue 3 示例
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const stats = ref({})
const loading = ref(false)
const fetchHomeStats = async (timeRange = null, typeIds = null) => {
loading.value = true
try {
const params = {}
if (timeRange) params.time_range = timeRange
if (typeIds) params.type_ids = typeIds
const { data } = await axios.get('/admin/statistics/home-data', { params })
stats.value = data
} catch (error) {
console.error('获取统计数据失败:', error)
} finally {
loading.value = false
}
}
onMounted(() => {
fetchHomeStats()
})
</script>
<template>
<div v-if="!loading">
<h2>今日待审核: {{ stats.today_pending_files }}</h2>
<h2>已审核: {{ stats.monthly_reviewed_files }}</h2>
<h2>通过率: {{ stats.monthly_pass_rate }}%</h2>
</div>
</template>
React 示例
import { useState, useEffect } from 'react'
import axios from 'axios'
function HomeStatistics() {
const [stats, setStats] = useState({})
const [loading, setLoading] = useState(false)
const fetchHomeStats = async (timeRange = null, typeIds = null) => {
setLoading(true)
try {
const params = {}
if (timeRange) params.time_range = timeRange
if (typeIds) params.type_ids = typeIds
const { data } = await axios.get('/admin/statistics/home-data', { params })
setStats(data)
} catch (error) {
console.error('获取统计数据失败:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
fetchHomeStats()
}, [])
return (
<div>
{!loading && (
<>
<h2>今日待审核: {stats.today_pending_files}</h2>
<h2>已审核: {stats.monthly_reviewed_files}</h2>
<h2>通过率: {stats.monthly_pass_rate}%</h2>
</>
)}
</div>
)
}
接口详情
完整URL
GET {BASE_URL}/admin/statistics/home-data
示例:
https://api.example.com/admin/statistics/home-data
http://localhost:8073/admin/statistics/home-data
请求头
| Header | 必填 | 类型 | 说明 | 示例 |
|---|---|---|---|---|
Authorization |
✅ 是 | String | JWT Token | Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... |
Content-Type |
❌ 否 | String | 内容类型 | application/json |
请求参数
Query 参数
| 参数名 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
type_ids |
❌ 否 | String | null |
文档类型ID,多个用逗号分隔 |
time_range |
❌ 否 | String | null |
时间范围,见下表 |
time_range 参数详解
| 值 | 说明 | 当前周期 | 对比周期 | 使用场景 |
|---|---|---|---|---|
| 不传参数 | 本月数据(默认) | 本月1日 ~ 当前时间 | 上月1日 ~ 上月最后一天 | 默认首页统计 |
today |
今天 | 今天00:00 ~ 当前时间 | 昨天00:00 ~ 昨天23:59 | 查看今日数据 |
3days |
近3天 | 当前时间向前72小时 | 再往前72小时 | 短期趋势 |
7days |
近7天 | 当前时间向前7天 | 再往前7天 | 周统计 |
30days |
近30天 | 当前时间向前30天 | 再往前30天 | 月统计 |
type_ids 参数详解
格式: 逗号分隔的整数
示例:
- 单个类型:
type_ids=1 - 多个类型:
type_ids=1,2,3 - 所有类型: 不传参数或传
null
有效值 (根据你的业务配置):
1 // 类型1
2 // 类型2
3 // 类型3
// ... 更多类型ID
响应数据
响应结构
interface HomeStatisticsResponse {
today_pending_files: number; // 今日待审核文件数
monthly_reviewed_files: number; // 当前周期已审核文件数
monthly_review_growth: GrowthData; // 审核数同比增长
monthly_pass_rate: number; // 当前周期通过率(百分比)
pass_rate_growth: GrowthData; // 通过率同比增长
issues_detected: number; // 检测到的问题总数
issues_growth: GrowthData; // 问题数同比增长
}
interface GrowthData {
value: number; // 增长百分比(绝对值)
is_up: boolean; // true=增长, false=下降
}
完整响应示例
{
"today_pending_files": 15,
"monthly_reviewed_files": 120,
"monthly_review_growth": {
"value": 25.5,
"is_up": true
},
"monthly_pass_rate": 85.3,
"pass_rate_growth": {
"value": 3.2,
"is_up": true
},
"issues_detected": 42,
"issues_growth": {
"value": 12.8,
"is_up": false
}
}
字段说明
1. today_pending_files(今日待审核文件数)
- 类型:
number - 说明: 今天新增的待审核文件数(audit_status = 0 或 null)
- 范围: >= 0
- 示例:
15
2. monthly_reviewed_files(当前周期已审核文件数)
- 类型:
number - 说明: 当前时间范围内已审核的文件数
- 包括状态:
- ✅
audit_status = 1(通过) - 🔄
audit_status = 2(审核中) - ❌
audit_status = -1(拒绝) - ⚠️
audit_status = -2(警告)
- ✅
- 范围: >= 0
- 示例:
120
3. monthly_review_growth(审核数同比增长)
- 类型:
GrowthData - 说明: 当前周期 vs 上个周期的审核数量变化
- 计算公式:
|(当前周期 - 上个周期) / 上个周期| * 100 - 示例:
{ "value": 25.5, // 增长了25.5% "is_up": true // 增长趋势 }
4. monthly_pass_rate(当前周期通过率)
- 类型:
number - 说明: 当前周期审核通过的文件占比
- 计算公式:
(通过数量 / 已审核总数) * 100 - 范围: 0.0 ~ 100.0
- 保留: 小数点后1位
- 示例:
85.3(表示85.3%)
5. pass_rate_growth(通过率同比增长)
- 类型:
GrowthData - 说明: 当前周期 vs 上个周期的通过率变化
- 计算公式:
|(当前通过率 - 上期通过率) / 上期通过率| * 100 - 示例:
{ "value": 3.2, // 通过率提升了3.2% "is_up": true }
6. issues_detected(检测到的问题总数)
- 类型:
number - 说明: 当前周期内所有评查点发现的问题总数
- 来源:
evaluation_results表中result='false'的记录 - 范围: >= 0
- 示例:
42
7. issues_growth(问题数同比增长)
- 类型:
GrowthData - 说明: 当前周期 vs 上个周期的问题数变化
- 示例:
{ "value": 12.8, // 问题数减少了12.8% "is_up": false // 下降趋势(好事) }
请求示例
1. 获取本月统计数据(默认)
请求:
curl -X GET "http://localhost:8073/admin/statistics/home-data" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript:
const response = await fetch('/admin/statistics/home-data', {
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await response.json()
响应:
{
"today_pending_files": 10,
"monthly_reviewed_files": 150,
"monthly_review_growth": {
"value": 15.5,
"is_up": true
},
"monthly_pass_rate": 82.0,
"pass_rate_growth": {
"value": 2.5,
"is_up": true
},
"issues_detected": 35,
"issues_growth": {
"value": 8.0,
"is_up": false
}
}
2. 获取今天的统计数据
请求:
curl -X GET "http://localhost:8073/admin/statistics/home-data?time_range=today" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript:
const response = await fetch('/admin/statistics/home-data?time_range=today', {
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await response.json()
Axios:
const { data } = await axios.get('/admin/statistics/home-data', {
params: { time_range: 'today' }
})
响应:
{
"today_pending_files": 5,
"monthly_reviewed_files": 12,
"monthly_review_growth": {
"value": 20.0,
"is_up": true
},
"monthly_pass_rate": 75.0,
"pass_rate_growth": {
"value": 5.0,
"is_up": false
},
"issues_detected": 8,
"issues_growth": {
"value": 10.0,
"is_up": false
}
}
3. 获取近7天统计数据
请求:
curl -X GET "http://localhost:8073/admin/statistics/home-data?time_range=7days" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript:
const response = await fetch('/admin/statistics/home-data?time_range=7days', {
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await response.json()
响应:
{
"today_pending_files": 8,
"monthly_reviewed_files": 85,
"monthly_review_growth": {
"value": 30.5,
"is_up": true
},
"monthly_pass_rate": 88.2,
"pass_rate_growth": {
"value": 4.0,
"is_up": true
},
"issues_detected": 25,
"issues_growth": {
"value": 15.0,
"is_up": false
}
}
4. 按文档类型筛选(单个类型)
请求:
curl -X GET "http://localhost:8073/admin/statistics/home-data?type_ids=1" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript:
const response = await fetch('/admin/statistics/home-data?type_ids=1', {
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await response.json()
Axios:
const { data } = await axios.get('/admin/statistics/home-data', {
params: { type_ids: '1' }
})
5. 按文档类型筛选(多个类型)
请求:
curl -X GET "http://localhost:8073/admin/statistics/home-data?type_ids=1,2,3" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript:
const typeIds = [1, 2, 3]
const response = await fetch(`/admin/statistics/home-data?type_ids=${typeIds.join(',')}`, {
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await response.json()
Axios:
const { data } = await axios.get('/admin/statistics/home-data', {
params: { type_ids: '1,2,3' }
})
6. 组合筛选:时间范围 + 文档类型
请求:
curl -X GET "http://localhost:8073/admin/statistics/home-data?time_range=7days&type_ids=1,2" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
JavaScript:
const params = new URLSearchParams({
time_range: '7days',
type_ids: '1,2'
})
const response = await fetch(`/admin/statistics/home-data?${params}`, {
headers: {
'Authorization': `Bearer ${token}`
}
})
const data = await response.json()
Axios:
const { data } = await axios.get('/admin/statistics/home-data', {
params: {
time_range: '7days',
type_ids: '1,2'
}
})
7. 完整的Vue组件示例(带下拉选择器)
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const stats = ref({})
const loading = ref(false)
const timeRange = ref(null)
const typeIds = ref(null)
// 时间范围选项
const timeRangeOptions = [
{ label: '本月', value: null },
{ label: '今天', value: 'today' },
{ label: '近3天', value: '3days' },
{ label: '近7天', value: '7days' },
{ label: '近30天', value: '30days' }
]
// 文档类型选项(根据实际业务调整)
const typeOptions = [
{ label: '全部类型', value: null },
{ label: '类型1', value: '1' },
{ label: '类型2', value: '2' },
{ label: '类型1+2', value: '1,2' }
]
const fetchStats = async () => {
loading.value = true
try {
const params = {}
if (timeRange.value) params.time_range = timeRange.value
if (typeIds.value) params.type_ids = typeIds.value
const { data } = await axios.get('/admin/statistics/home-data', { params })
stats.value = data
} catch (error) {
console.error('获取统计数据失败:', error)
} finally {
loading.value = false
}
}
onMounted(() => {
fetchStats()
})
</script>
<template>
<div class="home-statistics">
<!-- 筛选器 -->
<div class="filters">
<select v-model="timeRange" @change="fetchStats">
<option v-for="opt in timeRangeOptions" :key="opt.value" :value="opt.value">
{{ opt.label }}
</option>
</select>
<select v-model="typeIds" @change="fetchStats">
<option v-for="opt in typeOptions" :key="opt.value" :value="opt.value">
{{ opt.label }}
</option>
</select>
</div>
<!-- 统计数据展示 -->
<div v-if="!loading" class="stats-cards">
<div class="stat-card">
<h3>今日待审核</h3>
<p class="number">{{ stats.today_pending_files }}</p>
</div>
<div class="stat-card">
<h3>已审核文件</h3>
<p class="number">{{ stats.monthly_reviewed_files }}</p>
<p class="growth" :class="{ up: stats.monthly_review_growth?.is_up }">
{{ stats.monthly_review_growth?.is_up ? '↑' : '↓' }}
{{ stats.monthly_review_growth?.value }}%
</p>
</div>
<div class="stat-card">
<h3>审核通过率</h3>
<p class="number">{{ stats.monthly_pass_rate }}%</p>
<p class="growth" :class="{ up: stats.pass_rate_growth?.is_up }">
{{ stats.pass_rate_growth?.is_up ? '↑' : '↓' }}
{{ stats.pass_rate_growth?.value }}%
</p>
</div>
<div class="stat-card">
<h3>检测到的问题</h3>
<p class="number">{{ stats.issues_detected }}</p>
<p class="growth" :class="{ down: !stats.issues_growth?.is_up }">
{{ stats.issues_growth?.is_up ? '↑' : '↓' }}
{{ stats.issues_growth?.value }}%
</p>
</div>
</div>
<div v-else class="loading">加载中...</div>
</div>
</template>
<style scoped>
.filters {
display: flex;
gap: 16px;
margin-bottom: 24px;
}
.stats-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}
.stat-card {
padding: 20px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.number {
font-size: 32px;
font-weight: bold;
margin: 8px 0;
}
.growth {
font-size: 14px;
color: #666;
}
.growth.up {
color: #52c41a;
}
.growth.down {
color: #f5222d;
}
</style>
8. 完整的React组件示例(带Ant Design)
import { useState, useEffect } from 'react'
import { Card, Select, Spin, Statistic, Row, Col } from 'antd'
import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons'
import axios from 'axios'
const { Option } = Select
function HomeStatistics() {
const [stats, setStats] = useState({})
const [loading, setLoading] = useState(false)
const [timeRange, setTimeRange] = useState(null)
const [typeIds, setTypeIds] = useState(null)
// 时间范围选项
const timeRangeOptions = [
{ label: '本月', value: null },
{ label: '今天', value: 'today' },
{ label: '近3天', value: '3days' },
{ label: '近7天', value: '7days' },
{ label: '近30天', value: '30days' }
]
const fetchStats = async () => {
setLoading(true)
try {
const params = {}
if (timeRange) params.time_range = timeRange
if (typeIds) params.type_ids = typeIds
const { data } = await axios.get('/admin/statistics/home-data', { params })
setStats(data)
} catch (error) {
console.error('获取统计数据失败:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
fetchStats()
}, [timeRange, typeIds])
return (
<div style={{ padding: '24px' }}>
{/* 筛选器 */}
<div style={{ marginBottom: '24px', display: 'flex', gap: '16px' }}>
<Select
placeholder="选择时间范围"
value={timeRange}
onChange={setTimeRange}
style={{ width: 200 }}
>
{timeRangeOptions.map(opt => (
<Option key={opt.value} value={opt.value}>{opt.label}</Option>
))}
</Select>
<Select
placeholder="选择文档类型"
value={typeIds}
onChange={setTypeIds}
style={{ width: 200 }}
>
<Option value={null}>全部类型</Option>
<Option value="1">类型1</Option>
<Option value="2">类型2</Option>
<Option value="1,2">类型1+2</Option>
</Select>
</div>
{/* 统计卡片 */}
<Spin spinning={loading}>
<Row gutter={16}>
<Col span={6}>
<Card>
<Statistic
title="今日待审核"
value={stats.today_pending_files}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="已审核文件"
value={stats.monthly_reviewed_files}
suffix={
stats.monthly_review_growth && (
<span style={{
color: stats.monthly_review_growth.is_up ? '#52c41a' : '#f5222d',
fontSize: '14px'
}}>
{stats.monthly_review_growth.is_up ? <ArrowUpOutlined /> : <ArrowDownOutlined />}
{stats.monthly_review_growth.value}%
</span>
)
}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="审核通过率"
value={stats.monthly_pass_rate}
precision={1}
suffix="%"
valueStyle={{ color: '#3f8600' }}
/>
</Card>
</Col>
<Col span={6}>
<Card>
<Statistic
title="检测到的问题"
value={stats.issues_detected}
valueStyle={{ color: '#cf1322' }}
/>
</Card>
</Col>
</Row>
</Spin>
</div>
)
}
export default HomeStatistics
错误处理
常见错误码
| HTTP状态码 | 错误场景 | 响应示例 | 处理建议 |
|---|---|---|---|
200 |
✅ 成功 | 正常数据 | - |
400 |
参数错误 | {"detail": "time_range 参数值无效..."} |
检查参数格式 |
401 |
未认证 | {"detail": "未提供认证凭据"} |
检查Token是否传递 |
403 |
权限不足 | {"detail": "此接口仅限管理员访问"} |
检查用户权限 |
500 |
服务器错误 | {"detail": "获取首页统计数据失败..."} |
联系后端排查 |
错误响应格式
{
"detail": "错误描述信息"
}
错误示例
1. time_range 参数无效
请求:
curl "http://localhost:8073/admin/statistics/home-data?time_range=invalid"
响应: HTTP 400
{
"detail": "time_range 参数值无效,应为: today, 3days, 7days, 30days,实际为: invalid"
}
2. type_ids 参数格式错误
请求:
curl "http://localhost:8073/admin/statistics/home-data?type_ids=abc"
响应: HTTP 400
{
"detail": "type_ids 参数格式错误,应为逗号分隔的整数,实际为: abc"
}
3. Token过期或无效
请求:
curl "http://localhost:8073/admin/statistics/home-data" \
-H "Authorization: Bearer INVALID_TOKEN"
响应: HTTP 401
{
"detail": "认证凭据无效或已过期"
}
前端错误处理示例
const fetchStats = async () => {
try {
const { data } = await axios.get('/admin/statistics/home-data', {
params: { time_range: 'today' }
})
return data
} catch (error) {
// 处理不同的错误情况
if (error.response) {
switch (error.response.status) {
case 400:
console.error('参数错误:', error.response.data.detail)
// 提示用户检查筛选条件
break
case 401:
console.error('未认证,请重新登录')
// 跳转到登录页
window.location.href = '/login'
break
case 403:
console.error('权限不足')
// 提示用户权限不足
break
case 500:
console.error('服务器错误:', error.response.data.detail)
// 显示错误提示
break
default:
console.error('未知错误:', error)
}
} else if (error.request) {
console.error('网络错误,请检查网络连接')
} else {
console.error('请求配置错误:', error.message)
}
}
}
权限说明
三级权限体系
| 用户角色 | 权限范围 | 能看到的数据 | 示例 |
|---|---|---|---|
| 省级管理员 | 全省 | 所有地市的数据汇总 | 可以看到广州+深圳+梅州...所有地市 |
| 地市管理员 | 本地市 | 所在地市的所有用户数据 | 梅州管理员只能看梅州的数据 |
| 普通用户 | 个人 | 仅自己创建的文档数据 | 张三只能看张三的数据 |
权限判断逻辑
系统通过以下步骤判断用户权限:
-
查询用户角色
SELECT role_key FROM user_role JOIN roles ON user_role.role_id = roles.id WHERE user_role.user_id = {current_user_id} -
权限分配
role_key = 'province_admin'→ 省级管理员user_role = 'admin'或is_leader = true→ 地市管理员- 其他 → 普通用户
-
数据过滤
- 省级管理员:不过滤地市(
area = null) - 地市管理员:过滤地市(
area = '梅州') - 普通用户:过滤用户ID(
user_id = 123)
- 省级管理员:不过滤地市(
权限验证示例
省级管理员查询:
// Token中包含: { user_role: 'provincial_admin', area: '省级' }
const { data } = await axios.get('/admin/statistics/home-data')
// 返回全省所有数据
地市管理员查询:
// Token中包含: { user_role: 'admin', area: '梅州' }
const { data } = await axios.get('/admin/statistics/home-data')
// 只返回梅州的数据
普通用户查询:
// Token中包含: { user_id: 123, user_role: 'common', area: '梅州' }
const { data } = await axios.get('/admin/statistics/home-data')
// 只返回用户123的数据
注意事项
⚠️ 重要提示
-
Token必须有效
- Token必须包含在Authorization头中
- Token格式:
Bearer {token} - Token过期需要重新登录
-
参数大小写敏感
time_range=today✅time_range=Today❌time_range=TODAY❌
-
type_ids必须是整数
type_ids=1,2,3✅type_ids=1, 2, 3✅ (自动trim空格)type_ids=a,b,c❌
-
缓存机制
- 数据缓存20分钟
- 相同参数20分钟内返回缓存数据
- 不同参数会触发新的查询
-
时间范围对比
todayvs 昨天3daysvs 前3天7daysvs 前7天30daysvs 前30天- 默认(本月)vs 上月
📊 数据统计说明
-
"已审核"的定义
- 包括以下状态的文档:
- ✅
audit_status = 1(通过) - 🔄
audit_status = 2(审核中) - ❌
audit_status = -1(拒绝) - ⚠️
audit_status = -2(警告)
- ✅
- 不包括:
audit_status = 0(待审核)audit_status = null(未知)
- 包括以下状态的文档:
-
"今日待审核"的定义
- 仅统计今天00:00之后创建的文档
audit_status = 0或audit_status = null
-
通过率计算
- 公式:
(通过数量 / 已审核总数) * 100 - 只有
audit_status = 1算通过 - 如果已审核总数为0,通过率为0.0%
- 公式:
-
增长率计算
- 使用绝对值(不带正负号)
- 通过
is_up判断增长/下降 - 如果上期数据为0,增长率固定为100%
🔄 刷新策略建议
// 推荐的刷新策略
// 1. 首次加载
onMounted(() => fetchStats())
// 2. 定时刷新(5分钟)
setInterval(() => fetchStats(), 5 * 60 * 1000)
// 3. 用户切换筛选条件时立即刷新
watch([timeRange, typeIds], () => fetchStats())
// 4. 用户手动刷新
const handleRefresh = () => {
// 清除缓存的方式:随机添加时间戳(不推荐,会绕过缓存)
// const timestamp = Date.now()
// fetchStats({ _t: timestamp })
// 推荐:直接调用,利用缓存
fetchStats()
}
🎨 UI展示建议
-
增长指标展示
// 使用颜色区分增长/下降 const getGrowthColor = (growth) => { return growth.is_up ? '#52c41a' : '#f5222d' } // 使用图标 const getGrowthIcon = (growth) => { return growth.is_up ? '↑' : '↓' } -
数值格式化
// 大数值使用千分位 const formatNumber = (num) => { return num.toLocaleString('zh-CN') } // 示例: 1234 → 1,234 -
空数据处理
// 当数据为0时的友好提示 const displayValue = (value) => { return value > 0 ? value : '暂无数据' }
🐛 常见问题 FAQ
Q1: 为什么返回的数据都是0?
A: 可能的原因:
- 时间范围内没有文档(如选择"今天"但今天没创建文档)
- 文档类型筛选过滤掉了所有数据
- 用户权限限制(普通用户只能看自己的数据)
- 数据库中确实没有符合条件的数据
Q2: 为什么切换时间范围后数据没变化?
A: 可能是Redis缓存,等待20分钟缓存过期或者联系后端清除缓存。
Q3: 增长率为什么总是100%?
A: 当上个周期数据为0,当前周期有数据时,增长率固定显示100%。
Q4: 省级管理员和地市管理员看到的数据一样?
A: 如果省级管理员的地市也是"梅州",且数据库中只有梅州的数据,两者看到的会一样。省级管理员应该看到所有地市的汇总。
Q5: 通过率计算是否包含"审核中"的文档?
A: 通过率 = 通过数量 / 已审核总数。
- 已审核总数包含"审核中"(status=2)
- 但通过数量只计算status=1的文档
- 所以"审核中"会降低通过率
版本历史
| 版本 | 日期 | 更新内容 |
|---|---|---|
| v3.0 | 2025-11-22 | 🎉 新增时间范围筛选功能(today/3days/7days/30days) |
| v2.1 | 2025-11-22 | ✨ "已审核"统计包含"审核中"状态(audit_status=2) |
| v2.0 | 2025-11-20 | 🔒 完善三级权限隔离机制 |
| v1.0 | 2025-11-15 | 🚀 初始版本发布 |
技术支持
如有疑问,请联系后端开发团队或查看:
- 📖 完整API文档:
/docs/api/ - 🐛 问题反馈: GitHub Issues
- 💬 技术讨论: 开发团队微信群
文档生成时间: 2025-11-22 文档维护: 后端开发团队 最后更新: Claude Code 🤖