Commit 8bf47f2e by Performance System

1

parent 2611dc34
Pipeline #3155 passed with stage
in 55 seconds
...@@ -5,7 +5,7 @@ import os ...@@ -5,7 +5,7 @@ import os
import sys import sys
from pathlib import Path from pathlib import Path
PORT = 5174 PORT = 4001
class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler): class MyHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
......
...@@ -162,8 +162,8 @@ ...@@ -162,8 +162,8 @@
<h3>🔧 解决方案</h3> <h3>🔧 解决方案</h3>
<ol> <ol>
<li><strong>推荐方式</strong>:运行 <code>启动v86优化版本.bat</code> 脚本</li> <li><strong>推荐方式</strong>:运行 <code>启动v86优化版本.bat</code> 脚本</li>
<li>或者在命令行运行:<code>python -m http.server 5174</code></li> <li>或者在命令行运行:<code>python -m http.server 4001</code></li>
<li>然后访问:<code>http://localhost:5174</code></li> <li>然后访问:<code>http://localhost:4001</code></li>
<li>如果没有Python,可以安装Node.js后运行:<code>npx serve .</code></li> <li>如果没有Python,可以安装Node.js后运行:<code>npx serve .</code></li>
</ol> </ol>
</div> </div>
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"element-plus": "^2.4.4", "element-plus": "^2.4.4",
"express": "^5.1.0", "express": "^5.1.0",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"jspdf": "^3.0.1",
"jszip": "^3.10.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"uuid": "^11.1.0", "uuid": "^11.1.0",
......
...@@ -2,7 +2,7 @@ const http = require('http'); ...@@ -2,7 +2,7 @@ const http = require('http');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const PORT = 5174; const PORT = 4001;
// MIME类型映射 // MIME类型映射
const mimeTypes = { const mimeTypes = {
......
...@@ -2118,6 +2118,110 @@ export const useDataStore = defineStore('data', () => { ...@@ -2118,6 +2118,110 @@ export const useDataStore = defineStore('data', () => {
} }
/** /**
* 月度重置功能 - 每月1日自动执行
*/
const performMonthlyReset = () => {
try {
const currentDate = new Date()
const lastResetKey = 'last_monthly_reset'
const lastReset = localStorage.getItem(lastResetKey)
const currentMonthKey = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, '0')}`
// 检查是否需要重置(每月只重置一次)
if (!lastReset || lastReset !== currentMonthKey) {
console.log('🔄 执行月度重置...')
// 1. 先保存当前月份的统计数据
const saveSuccess = saveCurrentMonthStats()
if (!saveSuccess) {
console.warn('⚠️ 保存月度统计失败,但继续执行重置')
}
// 2. 清空所有机构的图片上传记录
institutions.value.forEach(institution => {
if (institution.images && institution.images.length > 0) {
console.log(`清空机构 ${institution.name}${institution.images.length} 张图片`)
institution.images = []
}
})
// 3. 保存重置后的数据
saveToStorage()
// 4. 记录重置时间
localStorage.setItem(lastResetKey, currentMonthKey)
localStorage.setItem('last_reset_time', new Date().toISOString())
console.log(`✅ ${currentMonthKey} 月度重置完成`)
console.log('- 已保存上月统计数据到历史记录')
console.log('- 已清空所有机构的图片上传记录')
console.log('- 用户分数将自动重新计算')
return true
}
return false // 本月已重置过
} catch (error) {
console.error('月度重置失败:', error)
return false
}
}
/**
* 检查并执行月度重置(系统启动时调用)
*/
const checkAndPerformMonthlyReset = () => {
const currentDate = new Date()
// 只在每月1-3日检查是否需要重置(给一些缓冲时间)
if (currentDate.getDate() <= 3) {
console.log('🔍 检查是否需要执行月度重置...')
return performMonthlyReset()
}
return false
}
/**
* 手动执行月度重置(管理员功能)
*/
const manualMonthlyReset = () => {
try {
console.log('🔄 手动执行月度重置...')
// 1. 保存当前统计数据
const saveSuccess = saveCurrentMonthStats()
if (!saveSuccess) {
throw new Error('保存月度统计失败')
}
// 2. 清空所有机构的图片
let clearedCount = 0
institutions.value.forEach(institution => {
if (institution.images && institution.images.length > 0) {
clearedCount += institution.images.length
institution.images = []
}
})
// 3. 保存数据
saveToStorage()
// 4. 更新重置记录
const currentDate = new Date()
const currentMonthKey = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, '0')}`
localStorage.setItem('last_monthly_reset', currentMonthKey)
localStorage.setItem('last_reset_time', new Date().toISOString())
console.log(`✅ 手动月度重置完成,清空了 ${clearedCount} 张图片`)
return { success: true, clearedCount }
} catch (error) {
console.error('手动月度重置失败:', error)
return { success: false, error: error.message }
}
}
/**
* 导出数据(用于备份) * 导出数据(用于备份)
*/ */
const exportData = () => { const exportData = () => {
...@@ -2307,6 +2411,9 @@ export const useDataStore = defineStore('data', () => { ...@@ -2307,6 +2411,9 @@ export const useDataStore = defineStore('data', () => {
getMonthStats, getMonthStats,
deleteMonthStats, deleteMonthStats,
clearAllHistoryStats, clearAllHistoryStats,
autoSaveMonthlyStats autoSaveMonthlyStats,
performMonthlyReset,
checkAndPerformMonthlyReset,
manualMonthlyReset
} }
}) })
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
<div class="user-info"> <div class="user-info">
<h2>{{ authStore.currentUser.name }} 的工作台</h2> <h2>{{ authStore.currentUser.name }} 的工作台</h2>
<p>负责机构:{{ userInstitutions.length }}</p> <p>负责机构:{{ userInstitutions.length }}</p>
<p class="period-info">当前统计周期:{{ currentPeriod }}</p>
</div> </div>
<div class="header-actions"> <div class="header-actions">
<el-button @click="handleLogout">退出登录</el-button> <el-button @click="handleLogout">退出登录</el-button>
...@@ -16,21 +17,21 @@ ...@@ -16,21 +17,21 @@
</div> </div>
<div class="container"> <div class="container">
<!-- 得分统计 --> <!-- 统计信息 -->
<div class="score-section"> <div class="score-section">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<div class="score-card"> <div class="score-card">
<div class="score-title">互动得分</div> <div class="score-title">已传机构数</div>
<div class="score-value">{{ interactionScore.toFixed(1) }}</div> <div class="score-value">{{ uploadedInstitutionsCount }}</div>
<div class="score-desc">每机构最多1分</div> <div class="score-desc">已上传图片的机构数量</div>
</div> </div>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<div class="score-card performance"> <div class="score-card performance">
<div class="score-title">绩效得分</div> <div class="score-title">完成率</div>
<div class="score-value">{{ performanceScore.toFixed(1) }}</div> <div class="score-value">{{ completionRate }}%</div>
<div class="score-desc">满分10分</div> <div class="score-desc">已传机构数/总负责机构数</div>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
...@@ -270,17 +271,44 @@ const filteredInstitutions = computed(() => { ...@@ -270,17 +271,44 @@ const filteredInstitutions = computed(() => {
}) })
/** /**
* 计算属性:互动得分 * 计算属性:已传机构数
*/ */
const interactionScore = computed(() => { const uploadedInstitutionsCount = computed(() => {
return dataStore.calculateInteractionScore(authStore.currentUser.id) return userInstitutions.value.filter(inst => inst.images && inst.images.length > 0).length
}) })
/** /**
* 计算属性:绩效得分 * 计算属性:完成率
*/ */
const performanceScore = computed(() => { const completionRate = computed(() => {
return dataStore.calculatePerformanceScore(authStore.currentUser.id) const totalInstitutions = userInstitutions.value.length
if (totalInstitutions === 0) return 0
return Math.round((uploadedInstitutionsCount.value / totalInstitutions) * 100)
})
/**
* 计算属性:当前统计周期
*/
const currentPeriod = computed(() => {
const currentDate = new Date()
const year = currentDate.getFullYear()
const month = currentDate.getMonth() + 1
// 获取上次重置时间
const lastResetTime = localStorage.getItem('last_reset_time')
if (lastResetTime) {
const resetDate = new Date(lastResetTime)
const resetMonth = resetDate.getMonth() + 1
const resetYear = resetDate.getFullYear()
// 如果是同一年同一月,显示重置后的天数
if (resetYear === year && resetMonth === month) {
const daysSinceReset = Math.floor((currentDate - resetDate) / (1000 * 60 * 60 * 24))
return `${year}${month}月(重置后第${daysSinceReset + 1}天)`
}
}
return `${year}${month}月`
}) })
/** /**
...@@ -1096,4 +1124,11 @@ onMounted(() => { ...@@ -1096,4 +1124,11 @@ onMounted(() => {
padding: 15px; padding: 15px;
} }
} }
</style>
\ No newline at end of file /* 周期信息样式 */
.period-info {
font-size: 12px;
color: #909399;
margin: 4px 0 0 0;
}
</style>
\ No newline at end of file
...@@ -54,6 +54,6 @@ echo ======================================== ...@@ -54,6 +54,6 @@ echo ========================================
echo. echo.
:: 直接调用vite :: 直接调用vite
.\node_modules\.bin\vite.cmd --host 127.0.0.1 --port 5174 .\node_modules\.bin\vite.cmd --host 127.0.0.1 --port 4001
pause pause
...@@ -8,5 +8,9 @@ export default defineConfig({ ...@@ -8,5 +8,9 @@ export default defineConfig({
alias: { alias: {
'@': '/src' '@': '/src'
} }
},
server: {
port: 4001,
host: '0.0.0.0'
} }
}) })
\ No newline at end of file \ No newline at end of file
@echo off @echo off
...@@ -62,7 +62,7 @@ if not exist "node_modules" ( ...@@ -62,7 +62,7 @@ if not exist "node_modules" (
echo 🚀 正在启动开发服务器... echo 🚀 正在启动开发服务器...
echo. echo.
echo 启动成功后,请在浏览器中访问显示的地址 echo 启动成功后,请在浏览器中访问显示的地址
echo 通常是: http://localhost:5173 或 http://localhost:5174 echo 通常是: http://localhost:4001
echo. echo.
echo 默认登录账号: echo 默认登录账号:
echo - 管理员: admin / admin123 echo - 管理员: admin / admin123
......
# 🚀 新功能演示指南 # 🚀 新功能演示指南
...@@ -196,7 +196,7 @@ const calculateImageHash = (imageUrl) => { ...@@ -196,7 +196,7 @@ const calculateImageHash = (imageUrl) => {
现在您可以开始体验这些新功能了! 现在您可以开始体验这些新功能了!
1. 访问 **http://localhost:5174/** 体验重复图片检测 1. 访问 **http://localhost:4001/** 体验重复图片检测
2. 使用管理员账户体验历史统计功能 2. 使用管理员账户体验历史统计功能
3. 使用测试工具验证功能正确性 3. 使用测试工具验证功能正确性
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment