feat: 内容数据迁移至数据库,合规审查全链路打通
- 文章 HTML 存储从文件系统迁移至 articles 表,删除 releases 目录 - 合规审查从 DB 读取 HTML,审查结果写回 DB,通过后自动推进至待发布 - 新增 todayCount 筛选按钮,与系统概览统计数据一致 - 全屏预览修复:提升 z-index 超过侧边栏,添加退出全屏/关闭按钮 - 统一 '优化' → '审查' 命名,消除前后端术语不一致 - 调度器创作完成后自动触发审查(生成 → 审查 → 待发布) - 清理旧备份/调试文件、过期大纲和研究笔记
This commit is contained in:
@@ -5,20 +5,31 @@
|
||||
function injectStyles() {
|
||||
if (document.getElementById('navigation-styles')) return;
|
||||
const styles = `
|
||||
.nav-wrapper, .navigation-wrapper { position: fixed; top: 60px; left: 0; bottom: 0; z-index: 9999; }
|
||||
.nav-wrapper .sidebar, .navigation-wrapper .sidebar { position: fixed; top: 60px; left: 0; bottom: 0; width: 180px; background: #fff; padding: 12px; box-shadow: 2px 0 8px rgba(0,0,0,0.1); overflow-y: auto; z-index: 99999; border-right: 1px solid #ebeef5; }
|
||||
.nav-wrapper .sidebar-header, .navigation-wrapper .sidebar-header { padding: 12px 8px 16px; border-bottom: 1px solid #ebeef5; margin-bottom: 12px; }
|
||||
.nav-wrapper .sidebar-header h3, .navigation-wrapper .sidebar-header h3 { margin: 0; font-size: 16px; font-weight: 600; color: #303133; }
|
||||
.nav-wrapper .sidebar-btn, .navigation-wrapper .sidebar-btn { width: 100%; text-align: left; padding: 10px 12px; border: none; background: transparent; border-radius: 8px; margin-bottom: 6px; cursor: pointer; transition: all 0.3s; color: #606266; font-size: 14px; display: flex; align-items: center; gap: 6px; }
|
||||
.nav-wrapper .sidebar-btn:hover, .navigation-wrapper .sidebar-btn:hover { background: #f5f7fa; color: #409eff; }
|
||||
.nav-wrapper .sidebar-btn.active, .navigation-wrapper .sidebar-btn.active { background: #ecf5ff; color: #409eff; font-weight: 600 !important; }
|
||||
.nav-wrapper .mobile-nav, .navigation-wrapper .mobile-nav { display: none; position: fixed; bottom: 0; left: 0; right: 0; background: #1890ff; box-shadow: 0 -2px 8px rgba(0,0,0,0.2); padding: 8px 0; z-index: 99999; justify-content: space-around; }
|
||||
.nav-wrapper .mobile-nav-btn, .navigation-wrapper .mobile-nav-btn { flex: 1; border: none; background: transparent; padding: 8px 4px; text-align: center; font-size: 11px; color: white !important; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 2px; }
|
||||
.nav-wrapper .mobile-nav-btn .nav-icon, .navigation-wrapper .mobile-nav-btn .nav-icon { font-size: 18px; line-height: 1; }
|
||||
.nav-wrapper .mobile-nav-btn .nav-text, .navigation-wrapper .mobile-nav-btn .nav-text { font-size: 10px; margin-top: 2px; }
|
||||
.nav-wrapper .mobile-nav-btn:hover, .navigation-wrapper .mobile-nav-btn:hover { background: rgba(255,255,255,0.2); }
|
||||
.nav-wrapper .mobile-nav-btn.active, .navigation-wrapper .mobile-nav-btn.active { background: rgba(255,255,255,0.3); font-weight: 600 !important; }
|
||||
@media (max-width: 768px) { .nav-wrapper .sidebar, .navigation-wrapper .sidebar { display: none !important; } .nav-wrapper .mobile-nav, .navigation-wrapper .mobile-nav { display: flex !important; } }
|
||||
.nav-wrapper, .navigation-wrapper { position: fixed; top: 60px; left: 0; bottom: 0; width: 180px; z-index: 9999; pointer-events: none; }
|
||||
.nav-wrapper .sidebar, .navigation-wrapper .sidebar { position: fixed; top: 60px; left: 0; bottom: 0; width: 180px; background: #fff; padding: 12px 8px; box-shadow: 2px 0 12px rgba(0,0,0,0.06); overflow-y: auto; z-index: 10000; border-right: 1px solid #ebeef5; pointer-events: auto; }
|
||||
.nav-wrapper .sidebar-header, .navigation-wrapper .sidebar-header { padding: 12px 12px 16px; border-bottom: 1px solid #f0f2f5; margin-bottom: 12px; }
|
||||
.nav-wrapper .sidebar-header h3, .navigation-wrapper .sidebar-header h3 { margin: 0; font-size: 15px; font-weight: 700; background: linear-gradient(135deg, #2563eb, #7c3aed); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; letter-spacing: -0.3px; }
|
||||
.nav-wrapper .sidebar-btn, .navigation-wrapper .sidebar-btn { width: 100%; text-align: left; padding: 10px 12px; border: none; background: transparent; border-radius: 10px; margin-bottom: 4px; cursor: pointer; transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); color: #606266; font-size: 13px; display: flex; align-items: center; gap: 8px; position: relative; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||
.nav-wrapper .sidebar-btn:hover, .navigation-wrapper .sidebar-btn:hover { background: #f0f4ff; color: #2563eb; transform: translateX(2px); }
|
||||
.nav-wrapper .sidebar-btn.active, .navigation-wrapper .sidebar-btn.active { background: linear-gradient(135deg, #eef2ff, #e0e7ff); color: #2563eb; font-weight: 600 !important; box-shadow: inset 3px 0 0 #2563eb; }
|
||||
.nav-wrapper .mobile-nav, .navigation-wrapper .mobile-nav { display: none; position: fixed; bottom: 0; left: 0; right: 0; background: linear-gradient(135deg, #2563eb, #1d4ed8); box-shadow: 0 -4px 20px rgba(37, 99, 235, 0.25); padding: 4px 0; z-index: 99999; justify-content: space-around; pointer-events: auto; }
|
||||
.nav-wrapper .mobile-nav-btn, .navigation-wrapper .mobile-nav-btn { flex: 1; border: none; background: transparent; padding: 4px 2px; text-align: center; font-size: 10px; color: rgba(255,255,255,0.8) !important; cursor: pointer; display: flex; flex-direction: column; align-items: center; gap: 0; transition: all 0.2s; border-radius: 8px; margin: 0 1px; min-width: 0; }
|
||||
.nav-wrapper .mobile-nav-btn .nav-icon, .navigation-wrapper .mobile-nav-btn .nav-icon { font-size: 16px; line-height: 1.2; }
|
||||
.nav-wrapper .mobile-nav-btn .nav-text, .navigation-wrapper .mobile-nav-btn .nav-text { font-size: 9px; margin-top: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
|
||||
.nav-wrapper .mobile-nav-btn:hover, .navigation-wrapper .mobile-nav-btn:hover { background: rgba(255,255,255,0.15); color: white !important; }
|
||||
.nav-wrapper .mobile-nav-btn.active, .navigation-wrapper .mobile-nav-btn.active { background: rgba(255,255,255,0.2); color: white !important; font-weight: 600 !important; }
|
||||
.mobile-more-backdrop { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.3); z-index: 100000; animation: fadeIn 0.2s ease-out; }
|
||||
.mobile-more-sheet { position: fixed; bottom: 0; left: 0; right: 0; background: white; border-radius: 16px 16px 0 0; box-shadow: 0 -8px 32px rgba(0,0,0,0.15); z-index: 100001; padding: 20px 16px calc(env(safe-area-inset-bottom) + 60px); animation: slideUp 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); max-height: 70vh; overflow-y: auto; pointer-events: auto; }
|
||||
.mobile-more-sheet .sheet-handle { width: 36px; height: 4px; background: #e0e0e0; border-radius: 2px; margin: 0 auto 16px; }
|
||||
.mobile-more-sheet .sheet-title { font-size: 16px; font-weight: 700; color: #303133; margin-bottom: 16px; text-align: center; }
|
||||
.mobile-more-sheet .sheet-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
|
||||
.mobile-more-sheet .sheet-item { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 12px 4px; border: none; background: transparent; border-radius: 12px; cursor: pointer; transition: all 0.2s; color: #606266; font-size: 12px; white-space: nowrap; }
|
||||
.mobile-more-sheet .sheet-item:hover { background: #f0f4ff; color: #2563eb; }
|
||||
.mobile-more-sheet .sheet-item.active { background: #eef2ff; color: #2563eb; font-weight: 600; }
|
||||
.mobile-more-sheet .sheet-item .item-icon { font-size: 24px; line-height: 1; }
|
||||
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
|
||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||
@media (max-width: 768px) { .nav-wrapper .sidebar, .navigation-wrapper .sidebar { display: none !important; } .nav-wrapper .mobile-nav, .navigation-wrapper .mobile-nav { display: flex !important; } body > #app > .main-content { padding-bottom: 56px !important; } }
|
||||
body > #app > .main-content { margin-left: 180px !important; padding-top: 60px !important; }
|
||||
@media (max-width: 768px) { body > #app > .main-content { margin-left: 0 !important; padding-bottom: 60px !important; } }
|
||||
`;
|
||||
@@ -55,36 +66,76 @@
|
||||
mobileNav.innerHTML = `
|
||||
<button class="mobile-nav-btn ${currentPage==='dashboard'?'active':''}" data-page="/"><span class="nav-icon">📊</span><span class="nav-text">首页</span></button>
|
||||
<button class="mobile-nav-btn ${currentPage==='topics'?'active':''}" data-page="topics.html"><span class="nav-icon">📋</span><span class="nav-text">选题</span></button>
|
||||
<button class="mobile-nav-btn ${currentPage==='tasks'?'active':''}" data-page="tasks.html"><span class="nav-icon">🚀</span><span class="nav-text">任务</span></button>
|
||||
<button class="mobile-nav-btn ${currentPage==='calendar'?'active':''}" data-page="calendar.html"><span class="nav-icon">📅</span><span class="nav-text">日历</span></button>
|
||||
<button class="mobile-nav-btn ${currentPage==='assets'?'active':''}" data-page="assets.html"><span class="nav-icon">🖼️</span><span class="nav-text">素材</span></button>
|
||||
<button class="mobile-nav-btn ${currentPage==='tasks'?'active':''}" data-page="tasks.html"><span class="nav-icon">🚀</span><span class="nav-text">任务</span></button>
|
||||
<button class="mobile-nav-btn" id="mobile-more-btn"><span class="nav-icon">⬆</span><span class="nav-text">更多</span></button>
|
||||
`;
|
||||
|
||||
// "更多"弹出菜单
|
||||
const sheetItems = [
|
||||
{ key: 'metrics', label: '数据分析', icon: '📊', page: 'metrics.html' },
|
||||
{ key: 'platforms', label: '平台配置', icon: '🌐', page: 'platforms.html' },
|
||||
{ key: 'logs', label: '系统日志', icon: '📄', page: 'logs.html' },
|
||||
{ key: 'users', label: '用户管理', icon: '👥', page: 'users.html', admin: true },
|
||||
{ key: 'admin', label: '系统管理', icon: '⚙️', page: 'admin.html', admin: true },
|
||||
];
|
||||
|
||||
const sheetItemsHtml = sheetItems.map(item =>
|
||||
`<button class="sheet-item ${currentPage===item.key?'active':''}" data-page="${item.page}"${item.admin ? ' data-admin="1"' : ''} style="${item.admin && !isAdmin ? 'display:none' : ''}">
|
||||
<span class="item-icon">${item.icon}</span><span>${item.label}</span>
|
||||
</button>`
|
||||
).join('');
|
||||
|
||||
const backdrop = document.createElement('div');
|
||||
backdrop.className = 'mobile-more-backdrop';
|
||||
backdrop.id = 'mobile-more-backdrop';
|
||||
backdrop.style.display = 'none';
|
||||
|
||||
const sheet = document.createElement('div');
|
||||
sheet.className = 'mobile-more-sheet';
|
||||
sheet.id = 'mobile-more-sheet';
|
||||
sheet.style.display = 'none';
|
||||
sheet.innerHTML = `<div class="sheet-handle"></div><div class="sheet-title">所有菜单</div><div class="sheet-grid">${sheetItemsHtml}</div>`;
|
||||
|
||||
const showMore = () => {
|
||||
backdrop.style.display = ''; sheet.style.display = '';
|
||||
};
|
||||
const hideMore = () => {
|
||||
backdrop.style.display = 'none'; sheet.style.display = 'none';
|
||||
};
|
||||
|
||||
// 绑定导航跳转
|
||||
const handleNavClick = (btn) => {
|
||||
const page = btn.getAttribute('data-page');
|
||||
if (!page) return;
|
||||
console.log('[Nav] 点击导航:', page);
|
||||
hideMore();
|
||||
if (onNavigate) { onNavigate(page); return; }
|
||||
const target = page === '/' ? '/' : (page.startsWith('/') ? page : '/' + page);
|
||||
window.location.href = target;
|
||||
};
|
||||
|
||||
wrapper.appendChild(sidebar);
|
||||
wrapper.appendChild(mobileNav);
|
||||
wrapper.appendChild(backdrop);
|
||||
wrapper.appendChild(sheet);
|
||||
|
||||
// 绑定点击事件
|
||||
wrapper.querySelectorAll('button').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
const page = btn.getAttribute('data-page');
|
||||
console.log('[Nav] 点击导航:', page);
|
||||
if (onNavigate) {
|
||||
onNavigate(page);
|
||||
} else {
|
||||
// 直接跳转 - 修复路径处理
|
||||
let target;
|
||||
if (page === '/' || page === '') {
|
||||
target = '/';
|
||||
} else if (page.startsWith('/')) {
|
||||
target = page;
|
||||
} else {
|
||||
target = '/' + page;
|
||||
}
|
||||
window.location.href = target;
|
||||
}
|
||||
});
|
||||
// 事件绑定
|
||||
wrapper.querySelectorAll('.sidebar-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => { e.preventDefault(); handleNavClick(btn); });
|
||||
});
|
||||
wrapper.querySelectorAll('.mobile-nav-btn').forEach(btn => {
|
||||
if (btn.id === 'mobile-more-btn') {
|
||||
btn.addEventListener('click', (e) => { e.preventDefault(); showMore(); });
|
||||
} else {
|
||||
btn.addEventListener('click', (e) => { e.preventDefault(); handleNavClick(btn); });
|
||||
}
|
||||
});
|
||||
wrapper.querySelectorAll('.sheet-item').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => { e.preventDefault(); handleNavClick(btn); });
|
||||
});
|
||||
backdrop.addEventListener('click', hideMore);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
@@ -233,10 +284,18 @@
|
||||
mobileItems: [
|
||||
{ key: 'dashboard', label: '首页', icon: '📊', page: '/' },
|
||||
{ key: 'topics', label: '选题', icon: '📋', page: 'topics.html' },
|
||||
{ key: 'tasks', label: '任务', icon: '🚀', page: 'tasks.html' },
|
||||
{ key: 'calendar', label: '日历', icon: '📅', page: 'calendar.html' },
|
||||
{ key: 'assets', label: '素材', icon: '🖼️', page: 'assets.html' },
|
||||
{ key: 'tasks', label: '任务', icon: '🚀', page: 'tasks.html' }
|
||||
]
|
||||
{ key: 'assets', label: '素材', icon: '🖼️', page: 'assets.html' }
|
||||
],
|
||||
sheetItems: [
|
||||
{ key: 'metrics', label: '数据分析', icon: '📊', page: 'metrics.html' },
|
||||
{ key: 'platforms', label: '平台配置', icon: '🌐', page: 'platforms.html' },
|
||||
{ key: 'logs', label: '系统日志', icon: '📄', page: 'logs.html' },
|
||||
{ key: 'users', label: '用户管理', icon: '👥', page: 'users.html', admin: true },
|
||||
{ key: 'admin', label: '系统管理', icon: '⚙️', page: 'admin.html', admin: true }
|
||||
],
|
||||
showMoreSheet: false
|
||||
};
|
||||
},
|
||||
template: `
|
||||
@@ -259,7 +318,19 @@
|
||||
<span class="nav-icon">{{ item.icon }}</span>
|
||||
<span class="nav-text">{{ item.label }}</span>
|
||||
</button>
|
||||
<button class="mobile-nav-btn" @click="showMoreSheet = !showMoreSheet"><span class="nav-icon">⬆</span><span class="nav-text">更多</span></button>
|
||||
</nav>
|
||||
<div v-if="showMoreSheet" class="mobile-more-backdrop" @click="showMoreSheet = false"></div>
|
||||
<div v-if="showMoreSheet" class="mobile-more-sheet">
|
||||
<div class="sheet-handle"></div>
|
||||
<div class="sheet-title">所有菜单</div>
|
||||
<div class="sheet-grid">
|
||||
<button v-for="item in sheetItems" :key="item.key" v-show="!item.admin || isAdmin" :class="['sheet-item', { active: currentPage === item.key }]" @click="navigate(item.page)">
|
||||
<span class="item-icon">{{ item.icon }}</span>
|
||||
<span>{{ item.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
methods: {
|
||||
|
||||
Reference in New Issue
Block a user