修复切换主题模式时审计趋势画布没有同步更新
This commit is contained in:
parent
4a7376c318
commit
daf4530753
@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763642480325" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22385" data-spm-anchor-id="a313x.search_index.0.i8.510d3a81Nn5QNN" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M485.07804233 555.34391534l364.24370884 250.41244254a464.06874467 464.06874467 0 0 1-375.48791719 189.82773266C218.28958704 995.58409054 11.12158537 791.84818736 11.12158537 540.53686189 11.12158537 289.20919308 218.28958704 85.47328989 473.83383398 85.47328989c3.80799497 0 7.46890001 0.45761314 11.24420835 0.5556731V555.34391534z" fill="#eb7627" p-id="22386" data-spm-anchor-id="a313x.search_index.0.i4.510d3a81Nn5QNN" class=""></path><path d="M1004.12573602 489.97061092H566.79467283V19.26647586c244.08757534 12.61704775 438.19725945 210.66547345 438.19725948 453.85416585 0 5.68747749-0.65373305 11.21152169-0.86619629 16.84996921z" fill="#f4ea2a" p-id="22387" data-spm-anchor-id="a313x.search_index.0.i5.510d3a81Nn5QNN" class=""></path><path d="M1021.3189151 539.00058924a446.43429582 446.43429582 0 0 1-51.67759716 207.91979467L575.97962211 543.74015381V539.00058924h445.33929299z" fill="#d81e06" p-id="22388" data-spm-anchor-id="a313x.search_index.0.i7.510d3a81Nn5QNN" class=""></path></svg>
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763817545189" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8513" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M835.8 220H188.2c-11.7 0-21.2 9.5-21.2 21.2v414.1c0 11.7 9.5 21.2 21.2 21.2h647.7c11.7 0 21.2-9.5 21.2-21.2V241.2c0-11.7-9.5-21.2-21.3-21.2z" fill="#3E4959" p-id="8514"></path><path d="M188.2 241.2h647.7v371.6H188.2z" fill="#D3E0EA" p-id="8515"></path><path d="M252.9 294.3h237.8v265.4H252.9zM524.7 294.3h206v88.1h-206zM524.7 413.3h206v146.5h-206z" fill="#FFFFFF" p-id="8516"></path><path d="M371.8 342.1c-46.9 0-84.9 38-84.9 84.9 0 46.9 38 84.9 84.9 84.9s84.9-38 84.9-84.9h-84.9v-84.9z" fill="#003DF0" p-id="8517"></path><path d="M382.5 331.5v84.9h84.9c0-46.9-38-84.9-84.9-84.9z" fill="#3A6EFF" p-id="8518"></path><path d="M587.8 371.5c-7.6 0-9.8-10.8-11.9-21.3-2.1-10.7-4.6-22.8-11.7-22.9h-0.1c-5.9 0-9.6 8.6-21.8 42-0.6 1.6-2.3 2.4-3.8 1.8-1.6-0.6-2.4-2.3-1.8-3.8 13.2-36.4 17.1-46 27.4-46h0.1c12 0.1 14.9 14.8 17.5 27.7 1.5 7.6 3.4 16.9 6.6 16.4 3.8-0.7 7.6-9.6 10.7-16.7 4-9.3 7.7-18 14.2-18.7 7.8-0.9 12.2 9.7 16.8 20.9 2 4.9 5.8 14.1 7.8 14.5 0 0 2.7-0.5 7.5-13.3 3.1-8.2 6.1-18.8 8.5-27.3 4.8-16.8 5.7-19.7 9-19.7h0.1c3.3 0 4.3 2.6 10.6 22.7 3.6 11.6 10.2 32.7 14 37 0.9-1.5 2.3-4.7 3.3-7.4 4.1-10.1 10.3-25.3 24-30.2 1.6-0.5 3.3 0.3 3.8 1.8s-0.3 3.3-1.8 3.8c-11.2 4-16.6 17.1-20.5 26.8-2.9 7.2-4.8 12-9.1 11.6-5.7-0.4-10.1-11.3-19.6-41.6-1.6-5-3.3-10.7-4.7-14.7-1 3.2-2.2 7.5-3.3 11.5-7.2 25.5-13 43.7-21 44.8-6.3 0.9-10-7.9-14.2-18.1-2.7-6.6-7.2-17.6-10.6-17.3-3 0.3-6.6 8.9-9.3 15.1-4.2 9.8-8.1 19-15.1 20.2-0.5 0.4-1.1 0.4-1.6 0.4z" fill="#003DF0" p-id="8519"></path><path d="M539.6 512h14.9v31.9h-14.9zM571.7 490.8h14.9v53.1h-14.9zM603.9 458.9h14.9v84.9h-14.9zM636 501.4h14.9v42.5H636zM668.2 480.1h14.9v63.7h-14.9zM700.3 512h14.9v31.9h-14.9z" fill="#34D9C9" p-id="8520"></path><path d="M448.3 676.6v106.2h127.4V676.6H448.3z m90.2 58.4c0 14.7-11.9 26.5-26.5 26.5s-26.5-11.9-26.5-26.5v-10.6c0-14.7 11.9-26.5 26.5-26.5s26.5 11.9 26.5 26.5V735z" fill="#6E7782" p-id="8521"></path><path d="M624.1 804H399.9c-5.5 0-10-4.5-10-10v-1.2c0-5.5 4.5-10 10-10h224.2c5.5 0 10 4.5 10 10v1.2c0 5.5-4.5 10-10 10z" fill="#3E4959" p-id="8522"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 2.3 KiB |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 1.3 KiB |
@ -538,8 +538,8 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover{
|
||||
|
||||
/* Dashboard icon - SVG */
|
||||
.icon-dashboard {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: inline-block;
|
||||
background-image: url('../assets/dashboard.svg');
|
||||
background-size: contain;
|
||||
|
||||
@ -155,6 +155,7 @@ const API = (() => {
|
||||
adminUsers: () => request('/admin/users'),
|
||||
resetPassword: (username, new_password) => request('/admin/reset-password', { method: 'POST', body: JSON.stringify({ username, new_password }) }),
|
||||
changePassword: (username, new_password) => request('/admin/change-password', { method: 'POST', body: JSON.stringify({ username, new_password }) }),
|
||||
deleteUser: username => request('/admin/delete-user', { method: 'POST', body: JSON.stringify({ username }) }),
|
||||
clearModule: module => request('/admin/clear', { method: 'POST', body: JSON.stringify({ module }) }),
|
||||
getNotifications: () => requestQuiet('/notifications'),
|
||||
getUnreadCount: () => requestQuiet('/notifications/unread-count'),
|
||||
|
||||
@ -35,6 +35,11 @@ const Dashboard = (() => {
|
||||
window.removeEventListener('resize', window.__dashboardResizeHandler);
|
||||
window.__dashboardResizeHandler = null;
|
||||
}
|
||||
// 清理主题切换监听器
|
||||
if(window.__dashboardThemeHandler){
|
||||
window.removeEventListener('themeChanged', window.__dashboardThemeHandler);
|
||||
window.__dashboardThemeHandler = null;
|
||||
}
|
||||
// 清理全局变量
|
||||
window.__auditBusy = false;
|
||||
window.__pddParams = null;
|
||||
@ -271,9 +276,30 @@ const Dashboard = (() => {
|
||||
ctx.fillText('圆通', padding.left + 98, 15);
|
||||
};
|
||||
|
||||
// 初始化缓存数据
|
||||
window.__auditCache = window.__auditCache || {pdd: [], yt: []};
|
||||
if(pdd.list && pdd.list.length > 0) window.__auditCache.pdd = pdd.list;
|
||||
if(yt.list && yt.list.length > 0) window.__auditCache.yt = yt.list;
|
||||
|
||||
// 初始绘制
|
||||
drawTrendChart(pdd.list, yt.list);
|
||||
|
||||
// 监听主题切换事件,立即重绘图表
|
||||
const themeChangeHandler = () => {
|
||||
// 使用缓存数据或初始数据
|
||||
const pddData = (window.__auditCache && window.__auditCache.pdd && window.__auditCache.pdd.length > 0)
|
||||
? window.__auditCache.pdd
|
||||
: pdd.list;
|
||||
const ytData = (window.__auditCache && window.__auditCache.yt && window.__auditCache.yt.length > 0)
|
||||
? window.__auditCache.yt
|
||||
: yt.list;
|
||||
drawTrendChart(pddData, ytData);
|
||||
};
|
||||
window.addEventListener('themeChanged', themeChangeHandler);
|
||||
|
||||
// 保存监听器引用以便清理
|
||||
window.__dashboardThemeHandler = themeChangeHandler;
|
||||
|
||||
// 添加鼠标悬停事件
|
||||
const canvas = document.getElementById('trend-chart');
|
||||
const tooltip = document.getElementById('chart-tooltip');
|
||||
@ -361,8 +387,7 @@ const Dashboard = (() => {
|
||||
};
|
||||
}
|
||||
|
||||
// 资源管理:缓存数据(已禁用自动清理)
|
||||
window.__auditCache = window.__auditCache || {pdd: [], yt: []};
|
||||
// 资源管理:缓存数据(已在初始化时创建)
|
||||
|
||||
// 优化的刷新函数:一次请求同时更新趋势图和列表
|
||||
const refreshAll = async() => {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Router.register('/settings', async () => {
|
||||
const me = await API.me().catch(()=>({}));
|
||||
const users = (me && me.role === 'superadmin') ? await API.adminUsers().catch(()=>({list:[]})) : {list:[]};
|
||||
const userList = (users.list||[]).map(u=>`<li><span>${u.username}</span><span class="badge">${u.role}</span></li>`).join('') || '<li>暂无用户</li>';
|
||||
const userList = (users.list||[]).map(u=>`<li style="display:flex;justify-content:space-between;align-items:center"><div><span style="margin-right:8px">${u.username}</span><span class="badge">${u.role}</span></div><button class="btn btn-secondary" data-delete-user="${u.username}" style="padding:4px 8px;font-size:12px">删除</button></li>`).join('') || '<li>暂无用户</li>';
|
||||
const html = `<div class="grid cols-2">
|
||||
<div class="card">
|
||||
<div style="font-weight:600;margin-bottom:16px">账户设置</div>
|
||||
@ -311,6 +311,28 @@ Router.register('/settings', async () => {
|
||||
API.toast(enabled ? '水印已启用' : '水印已关闭');
|
||||
}
|
||||
});
|
||||
|
||||
// 删除用户
|
||||
document.querySelectorAll('button[data-delete-user]')?.forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const username = btn.getAttribute('data-delete-user');
|
||||
if (!confirm(`确定要删除用户 "${username}" 吗?此操作不可恢复。`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
btn.disabled = true;
|
||||
try {
|
||||
await API.deleteUser(username);
|
||||
API.toast('用户已删除');
|
||||
// 刷新页面以更新用户列表
|
||||
setTimeout(() => Router.navigate('/settings'), 1000);
|
||||
} catch(e) {
|
||||
API.toast('删除失败');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
document.querySelectorAll('button[data-clear]')?.forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const mod = btn.getAttribute('data-clear');
|
||||
|
||||
@ -1541,6 +1541,53 @@ def add_user():
|
||||
return jsonify({'error': f'创建用户失败:{str(e)}'}), 500
|
||||
|
||||
|
||||
@app.post('/api/admin/delete-user')
|
||||
@require_login
|
||||
@require_any_role('superadmin')
|
||||
def delete_user():
|
||||
"""删除用户"""
|
||||
data = request.get_json() or {}
|
||||
username = (data.get('username') or '').strip()
|
||||
|
||||
if not username:
|
||||
return jsonify({'error': '用户名不能为空'}), 400
|
||||
|
||||
# 获取当前登录用户
|
||||
current_user = session.get('user')
|
||||
if current_user and current_user.get('username') == username:
|
||||
return jsonify({'error': '不能删除当前登录的用户'}), 400
|
||||
|
||||
conn = get_db()
|
||||
c = conn.cursor()
|
||||
|
||||
# 检查用户是否存在
|
||||
c.execute('SELECT id, role FROM users WHERE username=?', (username,))
|
||||
user = c.fetchone()
|
||||
if not user:
|
||||
conn.close()
|
||||
return jsonify({'error': '用户不存在'}), 404
|
||||
|
||||
# 检查是否是最后一个超级管理员
|
||||
if user['role'] == 'superadmin':
|
||||
c.execute('SELECT COUNT(*) as cnt FROM users WHERE role=?', ('superadmin',))
|
||||
count = c.fetchone()['cnt']
|
||||
if count <= 1:
|
||||
conn.close()
|
||||
return jsonify({'error': '不能删除最后一个超级管理员'}), 400
|
||||
|
||||
# 删除用户
|
||||
try:
|
||||
c.execute('DELETE FROM users WHERE username=?', (username,))
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
log('delete_user', f'username={username}')
|
||||
return jsonify({'ok': True, 'message': f'用户 {username} 已删除'})
|
||||
except Exception as e:
|
||||
conn.close()
|
||||
return jsonify({'error': f'删除用户失败:{str(e)}'}), 500
|
||||
|
||||
|
||||
@app.post('/api/admin/clear')
|
||||
@require_login
|
||||
@require_any_role('superadmin')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user