1171 lines
34 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>企业单点登录平台 - 应用中心</title>
<link rel="stylesheet" href="/css/all.min.css">
<style>
/* 基础样式保持不变 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'sans-serif';
color: #1e293b;
background: linear-gradient(to bottom, #f8fafc, #f1f5f9);
min-height: 100vh;
}
.container {
width: 100%;
max-width: 1280px;
margin: 0 auto;
padding: 0 1rem;
}
@media (min-width: 768px) {
.container {
padding: 0 1.5rem;
}
}
/* 自定义滚动条样式 */
::-webkit-scrollbar {
height: 4px;
width: 4px;
}
::-webkit-scrollbar-track {
background: transparent;
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
/* 动画类 */
.animate-in {
animation-fill-mode: both;
}
.fade-in {
animation-name: fadeIn;
animation-duration: 200ms;
}
.slide-in-from-top-2 {
animation-name: slideInFromTop;
animation-duration: 200ms;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideInFromTop {
from { transform: translateY(-8px); }
to { transform: translateY(0); }
}
/* 隐藏滚动条但保留功能 */
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
/* 顶部导航栏 */
header {
position: sticky;
top: 0;
z-index: 50;
background-color: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(12px);
border-bottom: 1px solid #e2e8f0;
transition: all 300ms;
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.75rem 0;
}
.brand {
display: flex;
align-items: center;
gap: 0.75rem;
}
.brand-icon {
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
background: linear-gradient(to bottom right, #4f46e5, #8b5cf6);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4px 6px -1px rgba(79, 70, 229, 0.1), 0 2px 4px -1px rgba(79, 70, 229, 0.06);
}
.brand-icon i {
color: white;
font-size: 1.25rem;
}
.brand-name {
font-size: 1.25rem;
font-weight: bold;
background-clip: text;
-webkit-background-clip: text;
color: transparent;
background-image: linear-gradient(to right, #3b82f6, #8b5cf6);
}
.search-user-area {
display: flex;
align-items: center;
gap: 1rem;
}
.search-box {
position: relative;
display: none;
}
@media (min-width: 768px) {
.search-box {
display: block;
}
}
.search-box input {
padding: 0.5rem 2.5rem 0.5rem 1rem;
border-radius: 9999px;
border: 1px solid #e2e8f0;
background-color: #f8fafc;
transition: all 300ms;
width: 14rem;
}
.search-box:hover input {
width: 16rem;
}
.search-box input:focus {
background-color: white;
outline: none;
ring: 2px solid rgba(59, 130, 246, 0.3);
border-color: #93c5fd;
width: 16rem;
}
.search-box i {
position: absolute;
left: 1rem;
top: 50%;
transform: translateY(-50%);
color: #94a3b8;
transition: color 300ms;
}
.search-box:focus-within i {
color: #3b82f6;
}
.user-menu-container {
position: relative;
}
.user-button {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.25rem;
border-radius: 9999px;
background-color: transparent;
border: none;
cursor: pointer;
transition: background-color 300ms;
}
.user-button:hover {
background-color: #f1f5f9;
}
.user-avatar {
width: 2.25rem;
height: 2.25rem;
border-radius: 9999px;
object-fit: cover;
border: 2px solid transparent;
transition: all 300ms;
}
.user-button:hover .user-avatar {
border-color: #e0e7ff;
box-shadow: 0 0 0 2px #e0e7ff;
}
.user-info {
display: none;
text-align: left;
}
@media (min-width: 768px) {
.user-info {
display: block;
}
}
.user-name {
font-size: 0.875rem;
font-weight: 500;
}
.user-email {
font-size: 0.75rem;
color: #64748b;
}
.user-menu-icon {
font-size: 0.75rem;
color: #94a3b8;
transition: transform 200ms;
}
.user-menu-icon.rotated {
transform: rotate(180deg);
}
.user-dropdown {
position: absolute;
right: 0;
top: calc(100% + 0.5rem);
width: 12rem;
background-color: white;
border-radius: 0.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
border: 1px solid #f1f5f9;
padding: 0.5rem 0;
z-index: 50;
display: none;
}
.user-dropdown.show {
display: block;
animation: fadeIn 200ms, slideInFromTop 200ms;
}
.user-dropdown a {
display: block;
padding: 0.5rem 1rem;
font-size: 0.875rem;
color: #334155;
text-decoration: none;
transition: all 300ms;
}
.user-dropdown a:hover {
background-color: #f8fafc;
color: #4f46e5;
}
.user-dropdown a i {
margin-right: 0.5rem;
color: #94a3b8;
}
.user-dropdown-divider {
border-top: 1px solid #f1f5f9;
margin: 0.5rem 0;
}
.user-dropdown .logout {
color: #dc2626;
}
.user-dropdown .logout:hover {
background-color: #fee2e2;
}
/* 主要内容区 */
main {
padding: 2rem 0;
min-height: 75vh;
}
.page-title {
margin-bottom: 2rem;
}
@media (min-width: 768px) {
.page-title {
margin-bottom: 3rem;
}
}
.page-title h2 {
font-size: clamp(1.75rem, 4vw, 2.5rem);
font-weight: bold;
color: #1e293b;
margin-bottom: 0.75rem;
background-clip: text;
-webkit-background-clip: text;
color: transparent;
background-image: linear-gradient(to right, #1e293b, #64748b);
}
.page-title p {
color: #64748b;
max-width: 36rem;
}
/* 排序和分组控制区 */
.controls-container {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1.5rem;
flex-wrap: wrap;
gap: 1rem;
}
/* 应用分组导航 */
.group-nav {
overflow-x: auto;
padding-bottom: 0.5rem;
flex-grow: 1;
}
.group-buttons {
display: flex;
gap: 0.5rem;
min-width: max-content;
}
.group-button {
padding: 0.625rem 1.25rem;
border-radius: 9999px;
transition: all 300ms;
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.875rem;
white-space: nowrap;
background-color: white;
color: #334155;
border: 1px solid #e2e8f0;
cursor: pointer;
}
.group-button:hover {
background-color: #f8fafc;
border-color: #e0e7ff;
}
.group-button.active {
background-color: #4f46e5;
color: white;
box-shadow: 0 4px 6px -1px rgba(79, 70, 229, 0.25);
border-color: transparent;
}
/* 排序控制 */
.sort-control {
display: flex;
align-items: center;
gap: 0.5rem;
background-color: white;
border: 1px solid #e2e8f0;
border-radius: 9999px;
padding: 0.375rem;
white-space: nowrap;
}
.sort-label {
font-size: 0.875rem;
color: #64748b;
padding-left: 0.75rem;
}
.sort-button {
padding: 0.25rem 0.75rem;
border-radius: 9999px;
border: none;
background-color: transparent;
color: #334155;
font-size: 0.875rem;
cursor: pointer;
transition: all 300ms;
}
.sort-button.active {
background-color: #4f46e5;
color: white;
}
.sort-button:not(.active):hover {
background-color: #f8fafc;
}
/* 应用列表网格 */
.apps-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1.25rem;
}
@media (min-width: 640px) {
.apps-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (min-width: 1024px) {
.apps-grid {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1280px) {
.apps-grid {
grid-template-columns: repeat(4, 1fr);
}
}
/* 应用卡片 */
.app-card {
background-color: white;
border-radius: 1rem;
border: 1px solid #f1f5f9;
overflow: hidden;
cursor: pointer;
transition: all 300ms;
position: relative;
}
.app-card:hover {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
transform: translateY(-0.25rem);
}
.app-card-header {
padding: 1.25rem 1.25rem 0;
}
.app-header-content {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.app-icon-container {
width: 3.5rem;
height: 3.5rem;
border-radius: 0.5rem;
overflow: hidden;
border: 2px solid #f1f5f9;
transition: border-color 300ms;
}
.app-card:hover .app-icon-container {
border-color: #e0e7ff;
}
.app-icon {
width: 100%;
height: 100%;
object-fit: cover;
}
.app-tags {
display: flex;
gap: 0.25rem;
}
.app-tag {
padding: 0.125rem 0.5rem;
font-size: 0.75rem;
border-radius: 9999px;
}
.tag-recent {
background-color: #e0e7ff;
color: #4f46e5;
}
.tag-frequent {
background-color: #fed7d7;
color: #dc2626;
}
.app-card-body {
padding: 1.25rem;
padding-top: 1rem;
}
.app-title-container {
margin-bottom: 0.5rem;
}
.app-name {
font-weight: 600;
color: #1e293b;
margin-bottom: 0.25rem;
transition: color 300ms;
}
.app-card:hover .app-name {
color: #4f46e5;
}
.app-group {
font-size: 0.75rem;
color: #64748b;
}
.app-description {
font-size: 0.875rem;
color: #475569;
margin-bottom: 1rem;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
overflow: hidden;
}
.app-card-footer {
display: flex;
align-items: center;
justify-content: space-between;
padding-top: 0.5rem;
border-top: 1px solid #f8fafc;
}
.app-usage {
display: flex;
align-items: center;
}
.app-usage i {
font-size: 0.75rem;
color: #94a3b8;
margin-right: 0.25rem;
}
.usage-count {
font-size: 0.75rem;
color: #64748b;
}
.app-action {
width: 2rem;
height: 2rem;
border-radius: 9999px;
background-color: #f8fafc;
display: flex;
align-items: center;
justify-content: center;
color: #94a3b8;
transition: all 300ms;
}
.app-card:hover .app-action {
background-color: #e0e7ff;
color: #4f46e5;
}
.app-action i {
font-size: 0.875rem;
}
.app-accent {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 0.375rem;
opacity: 0;
transition: opacity 300ms;
}
.app-card:hover .app-accent {
opacity: 1;
}
/* 无搜索结果时的空状态 */
.empty-state {
grid-column: 1 / -1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 4rem 0;
text-align: center;
}
.empty-icon-container {
width: 6rem;
height: 6rem;
margin-bottom: 1.25rem;
background-color: #f8fafc;
border-radius: 9999px;
display: flex;
align-items: center;
justify-content: center;
}
.empty-icon {
color: #cbd5e1;
font-size: 4rem;
}
.empty-title {
font-size: 1.25rem;
font-weight: 500;
color: #1e293b;
margin-bottom: 0.5rem;
}
.empty-message {
color: #64748b;
max-width: 24rem;
margin-bottom: 1.5rem;
}
.reset-button {
padding: 0.5rem 1rem;
background-color: #4f46e5;
color: white;
border-radius: 0.5rem;
border: none;
cursor: pointer;
transition: background-color 300ms;
font-size: 0.875rem;
display: flex;
align-items: center;
gap: 0.25rem;
}
.reset-button:hover {
background-color: #4338ca;
}
/* 页脚 */
footer {
background-color: white;
border-top: 1px solid #e2e8f0;
margin-top: 4rem;
}
.footer-content {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 2rem 0;
}
@media (min-width: 768px) {
.footer-content {
flex-direction: row;
}
}
.copyright {
font-size: 0.875rem;
color: #64748b;
margin-bottom: 1rem;
}
@media (min-width: 768px) {
.copyright {
margin-bottom: 0;
}
}
</style>
</head>
<body>
<div class="min-h-screen bg-gradient-to-b from-slate-50 to-slate-100 font-sans text-slate-800">
<!-- 顶部导航栏 -->
<header class="sticky top-0 z-50 bg-white/80 backdrop-blur-md border-b border-slate-200 transition-all duration-300">
<div class="container">
<div class="header-content">
<!-- 品牌标识 -->
<div class="brand">
<div class="brand-icon">
<i class="fa fa-key text-white text-xl"></i>
</div>
<h1 class="brand-name">企业单点登录平台</h1>
</div>
<!-- 搜索与用户区域 -->
<div class="search-user-area">
<!-- 搜索框 -->
<div class="search-box">
<input
type="text"
placeholder="搜索应用..."
class="pl-10 pr-4 py-2 rounded-full border border-slate-200 bg-slate-50 focus:bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500/30 focus:border-indigo-300 transition-all w-56"
>
</div>
<!-- 用户信息与菜单 -->
<div class="user-menu-container">
<button class="user-button" id="userButton">
<img
src="${user.avatar}"
alt="用户头像"
class="user-avatar"
>
<div class="user-info">
<p class="user-name">${user.username}</p>
<p class="user-email">${user.email}</p>
</div>
<i class="fa fa-chevron-down user-menu-icon" id="userMenuIcon"></i>
</button>
<!-- 用户菜单 -->
<div class="user-dropdown" id="userDropdown">
<#-- <a href="#" class="dropdown-item">-->
<#-- <i class="fa fa-user mr-2 text-slate-400"></i>个人资料-->
<#-- </a>-->
<#-- <a href="#" class="dropdown-item">-->
<#-- <i class="fa fa-cog mr-2 text-slate-400"></i>账户设置-->
<#-- </a>-->
<#-- <div class="user-dropdown-divider"></div>-->
<a href="/logout" class="dropdown-item logout">
<i class="fa fa-sign-out mr-2"></i>退出登录
</a>
</div>
</div>
</div>
</div>
</div>
</header>
<!-- 主要内容区 -->
<main class="container">
<!-- 页面标题区 -->
<div class="page-title">
<h2>应用中心</h2>
<p>
一站式访问您的所有企业应用,通过单点登录快速安全地接入各类业务系统
</p>
</div>
<!-- 排序和分组控制区 -->
<div class="controls-container">
<!-- 应用分组导航 -->
<div class="group-nav scrollbar-hide">
<div class="group-buttons">
<button class="group-button active" data-group="all">
<i class="fa fa-check-circle"></i>
<span>全部应用</span>
</button>
<#list appGroup as item>
<button class="group-button" data-group="${item.ssoAppGroupId}">
<i class="fa fa-th-large"></i>
<span>${item.name}</span>
</button>
</#list>
</div>
</div>
<!-- 排序控制 -->
<div class="sort-control">
<span class="sort-label">排序方式:</span>
<button class="sort-button active" data-sort="usage">按使用次数</button>
<button class="sort-button" data-sort="default">默认排序</button>
</div>
</div>
<!-- 应用列表网格 -->
<div class="apps-grid" id="appsGrid">
<!-- 应用卡片1 -->
<#list appList as item>
<div class="app-card" data-group="${item.ssoAppGroupId}" data-id="${item.ssoAppId}" data-url="${item.appUrl! '/'}">
<div class="app-card-header">
<div class="app-header-content">
<div class="app-icon-container">
<img src="${item.appIcon}" alt="${item.appName}" class="app-icon">
</div>
<div class="app-tags">
<span class="app-tag tag-recent">最近</span>
<span class="app-tag tag-frequent">常用</span>
</div>
</div>
</div>
<div class="app-card-body">
<div class="app-title-container">
<h3 class="app-name">${item.appName}</h3>
<p class="app-group">${item.ssoAppGroup.name}</p>
</div>
<p class="app-description">${item.remark}</p>
<div class="app-card-footer">
<div class="app-usage">
<i class="fa fa-signal"></i>
<span class="usage-count">0次使用</span>
</div>
<div class="app-action">
<i class="fa fa-arrow-right"></i>
</div>
</div>
</div>
<div class="app-accent" style="background-color: #4f46e5;"></div>
</div>
</#list>
</div>
</main>
<!-- 页脚 -->
<footer>
<div class="container">
<div class="footer-content">
<div class="copyright">
&copy; 2025 企业单点登录平台. 保留所有权利.
</div>
</div>
</div>
</footer>
</div>
<script>
// 应用使用数据管理
let appUsageData = {};
const APPS_STORAGE_KEY = 'appUsageData';
const DEFAULT_SORT = 'usage'; // 默认按使用次数排序
let currentSort = DEFAULT_SORT;
let currentGroup = 'all';
let currentSearch = '';
// 从本地存储加载应用使用数据
function loadAppUsageData() {
try {
const storedData = localStorage.getItem(APPS_STORAGE_KEY);
if (storedData) {
appUsageData = JSON.parse(storedData);
}
} catch (error) {
console.error('加载应用使用数据失败:', error);
appUsageData = {};
}
// 更新UI显示
updateUsageCounts();
}
// 保存应用使用数据到本地存储
function saveAppUsageData() {
try {
localStorage.setItem(APPS_STORAGE_KEY, JSON.stringify(appUsageData));
} catch (error) {
console.error('保存应用使用数据失败:', error);
}
}
// 更新应用使用次数
function updateAppUsage(appId) {
// 确保应用ID存在于数据中
if (!appUsageData[appId]) {
// 从DOM获取初始计数
const card = document.querySelector(`.app-card[data-id="`+appId+`"]`);
const countElem = card.querySelector('.usage-count');
const initialCount = parseInt(countElem.textContent) || 0;
appUsageData[appId] = initialCount;
}
// 增加使用次数
appUsageData[appId]++;
// 保存数据
saveAppUsageData();
// 更新UI
updateUsageCounts();
// 如果当前是按使用次数排序,则重新排序
if (currentSort === 'usage') {
sortApps();
}
}
// 更新UI上的使用次数显示
function updateUsageCounts() {
const appCards = document.querySelectorAll('.app-card');
appCards.forEach(card => {
const appId = card.getAttribute('data-id');
const countElem = card.querySelector('.usage-count');
// 获取当前计数
let count = appUsageData[appId];
// 如果没有记录,使用初始值
if (count === undefined) {
count = parseInt(countElem.textContent) || 0;
appUsageData[appId] = count;
}
// 更新显示
countElem.textContent = count+`次使用`;
// 更新标签 - 如果使用次数超过70标记为常用
const tagContainer = card.querySelector('.app-tags');
let frequentTag = card.querySelector('.tag-frequent');
if (count > 70) {
if (!frequentTag) {
frequentTag = document.createElement('span');
frequentTag.className = 'app-tag tag-frequent';
frequentTag.textContent = '常用';
tagContainer.appendChild(frequentTag);
}
} else if (frequentTag) {
frequentTag.remove();
}
});
// 保存更新后的数据
saveAppUsageData();
}
// 对应用进行排序
function sortApps() {
const appsGrid = document.getElementById('appsGrid');
const appCards = Array.from(document.querySelectorAll('.app-card'));
// 根据当前排序方式排序
if (currentSort === 'usage') {
// 按使用次数降序排序
appCards.sort((a, b) => {
const idA = a.getAttribute('data-id');
const idB = b.getAttribute('data-id');
const countA = appUsageData[idA] || parseInt(a.querySelector('.usage-count').textContent) || 0;
const countB = appUsageData[idB] || parseInt(b.querySelector('.usage-count').textContent) || 0;
return countB - countA;
});
} else {
// 默认排序 - 按ID升序
appCards.sort((a, b) => {
const idA = parseInt(a.getAttribute('data-id'));
const idB = parseInt(b.getAttribute('data-id'));
return idA - idB;
});
}
// 先隐藏所有卡片,用于动画效果
appCards.forEach(card => {
card.style.opacity = '0';
card.style.transform = 'translateY(10px)';
});
// 重新添加到容器中(已排序)
appCards.forEach(card => {
appsGrid.appendChild(card);
// 添加动画效果
setTimeout(() => {
card.style.transition = 'opacity 0.3s, transform 0.3s';
card.style.opacity = '1';
card.style.transform = 'translateY(0)';
}, 50);
});
}
// 筛选应用(按组和搜索)
function filterApps() {
const appCards = document.querySelectorAll('.app-card');
appCards.forEach(card => {
const group = card.getAttribute('data-group');
const appName = card.querySelector('.app-name').textContent.toLowerCase();
const appDesc = card.querySelector('.app-description').textContent.toLowerCase();
const appGroup = card.querySelector('.app-group').textContent.toLowerCase();
// 组筛选
const groupMatch = currentGroup === 'all' || group === currentGroup;
// 搜索筛选
const searchMatch = !currentSearch ||
appName.includes(currentSearch) ||
appDesc.includes(currentSearch) ||
appGroup.includes(currentSearch);
// 显示或隐藏卡片
if (groupMatch && searchMatch) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
}
// 排序应用
function sortApps() {
// 先获取当前可见的应用
const visibleApps = Array.from(document.querySelectorAll('.app-card')).filter(card => {
return card.style.display !== 'none';
});
// 对可见应用进行排序
if (currentSort === 'usage') {
visibleApps.sort((a, b) => {
const idA = a.getAttribute('data-id');
const idB = b.getAttribute('data-id');
const countA = appUsageData[idA] || parseInt(a.querySelector('.usage-count').textContent) || 0;
const countB = appUsageData[idB] || parseInt(b.querySelector('.usage-count').textContent) || 0;
return countB - countA;
});
} else {
// 默认排序 - 按ID升序
visibleApps.sort((a, b) => {
const idA = parseInt(a.getAttribute('data-id'));
const idB = parseInt(b.getAttribute('data-id'));
return idA - idB;
});
}
// 重新排列可见应用
const appsGrid = document.getElementById('appsGrid');
visibleApps.forEach(card => {
appsGrid.appendChild(card);
});
}
// 初始化
function init() {
// 加载应用使用数据
loadAppUsageData();
// 用户菜单交互
const userButton = document.getElementById('userButton');
const userDropdown = document.getElementById('userDropdown');
const userMenuIcon = document.getElementById('userMenuIcon');
userButton.addEventListener('click', () => {
userDropdown.classList.toggle('show');
userMenuIcon.classList.toggle('rotated');
});
// 点击外部关闭用户菜单
document.addEventListener('click', (event) => {
if (!userButton.contains(event.target) && !userDropdown.contains(event.target)) {
userDropdown.classList.remove('show');
userMenuIcon.classList.remove('rotated');
}
});
// 应用分组筛选
const groupButtons = document.querySelectorAll('.group-button');
groupButtons.forEach(button => {
button.addEventListener('click', () => {
// 更新按钮状态
groupButtons.forEach(btn => {
btn.classList.remove('active');
btn.querySelector('i').className = 'fa fa-th-large';
});
button.classList.add('active');
button.querySelector('i').className = 'fa fa-check-circle';
// 更新当前组
currentGroup = button.getAttribute('data-group');
// 筛选应用
filterApps();
// 排序应用
sortApps();
});
});
// 应用点击事件
const appCards = document.querySelectorAll('.app-card');
appCards.forEach(card => {
card.addEventListener('click', () => {
const appId = card.getAttribute('data-id');
const appName = card.querySelector('.app-name').textContent;
// 更新使用次数
updateAppUsage(appId);
// 排序应用
sortApps();
console.log(`登录到应用: `+appName);
const url = card.getAttribute("data-url");
window.open(url, '_blank');
// 在实际应用中,这里会跳转到对应的应用
});
});
// 搜索功能
const searchInput = document.querySelector('.search-box input');
searchInput.addEventListener('input', () => {
currentSearch = searchInput.value.toLowerCase().trim();
// 筛选应用
filterApps();
// 排序应用
sortApps();
});
// 排序控制
const sortButtons = document.querySelectorAll('.sort-button');
sortButtons.forEach(button => {
button.addEventListener('click', () => {
// 更新按钮状态
sortButtons.forEach(btn => {
btn.classList.remove('active');
});
button.classList.add('active');
// 更新当前排序方式
currentSort = button.getAttribute('data-sort');
// 排序应用
sortApps();
});
});
// 排序应用
sortApps();
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>