EJS 语法问题无法找到“<%-" in node js

问题描述 投票:0回答:1

我正在创建仪表板,其中我为侧边栏创建了布局,并且侧边栏的不同页面具有不同的内容。

这是layout.ejs:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= pageTitle %></title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
    <%- css %>
    <style>
        :root {
            --primary-bg: #ffffff;
            --secondary-bg: #f3f4f6;
            --dark-bg: #111827;
            --sidebar-width: 280px;
            --header-height: 70px;
            --primary-color: #030a13;
            --text-primary: #111827;
            --text-secondary: #6b7280;
            --border-color: #e5e7eb;
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Inter', sans-serif;
        }

        body {
            background-color: var(--secondary-bg);
        }
        .sidebar {
            width: var(--sidebar-width);
            background: var(--dark-bg);
            height: 100vh;
            position: fixed;
            left: 0;
            top: 0;
            z-index: 1000;
            transition: all 0.3s ease;
            box-shadow: 4px 0 10px rgba(0, 0, 0, 0.1);
        }

        .sidebar-header {
            height: var(--header-height);
            display: flex;
            align-items: center;
            padding: 0 24px;
            border-bottom: 1px solid rgba(255, 255, 255, 0.1);
        }

        .sidebar-brand {
            color: white;
            font-size: 24px;
            font-weight: 700;
            text-decoration: none;
            letter-spacing: 0.5px;
        }

        .sidebar-menu {
            padding: 24px 0;
        }

        .menu-title {
            color: #6b7280;
            font-size: 12px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
            padding: 0 24px;
            margin: 20px 0 10px;
        }

        .menu-item {
            padding: 0 12px;
            margin: 4px 0;
        }

        .menu-link {
            display: flex;
            align-items: center;
            padding: 12px;
            color: #9ca3af;
            text-decoration: none;
            border-radius: 8px;
            transition: all 0.2s ease;
        }

        .menu-link:hover {
            background: rgba(255, 255, 255, 0.1);
            color: white;
        }

        .menu-link.active {
            background: var(--primary-color);
            color: white;
        }

        .menu-icon {
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-right: 12px;
        }

        .menu-text {
            font-size: 14px;
            font-weight: 500;
        }
        .main-content {
            margin-left: var(--sidebar-width);
            min-height: 100vh;
            background: var(--secondary-bg);
            padding: 24px;
        }

        .top-bar {
            height: var(--header-height);
            background: var(--primary-bg);
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 24px;
            margin: -24px -24px 24px;
            border-bottom: 1px solid var(--border-color);
        }

        .page-title {
            font-size: 24px;
            font-weight: 600;
            color: var(--text-primary);
        }

        .user-menu {
            display: flex;
            align-items: center;
            gap: 16px;
        }

        .notifications {
            position: relative;
            cursor: pointer;
        }

        .notification-icon {
            color: var(--text-primary);
            font-size: 30px;
        }

        .notification-badge {
            position: absolute;
            top: -6px;
            right: -6px;
            background: #ef4444;
            color: white;
            font-size: 10px;
            font-weight: 600;
            padding: 1px 5px;
            border-radius: 10px;
            border: 2px solid var(--primary-bg);
        }

        .user-profile {
            display: flex;
            align-items: center;
            gap: 12px;
            cursor: pointer;
            padding: 8px;
            border-radius: 8px;
            transition: all 0.2s ease;
        }

        .user-profile:hover {
            background: var(--secondary-bg);
        }

        .user-avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            object-fit: cover;
        }

        .user-info {
            line-height: 1.3;
        }

        .user-name {
            font-size: 14px;
            font-weight: 600;
            color: var(--text-primary);
        }

        .user-role {
            font-size: 12px;
            color: var(--text-secondary);
        }

        /* Content wrapper */
        .content-wrapper {
            max-width: 1600px;
            margin: 0 auto;
        }

        /* Responsive */
        @media (max-width: 1024px) {
            .sidebar {
                transform: translateX(-100%);
            }
            
            .main-content {
                margin-left: 0;
            }
            
            .sidebar.active {
                transform: translateX(0);
            }
        }
        .user-profile {
    position: relative;
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
    padding: 8px;
    border-radius: 8px;
    transition: all 0.2s ease;
}

.user-profile:hover {
    background: var(--secondary-bg);
}

.user-profile:hover .dropdown-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

.dropdown-menu {
    position: absolute;
    top: 100%;
    right: 0;
    background: white;
    border: 1px solid var(--border-color);
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
    padding: 8px 0;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-10px);
    transition: all 0.2s ease-in-out;
    z-index: 10;
}

.dropdown-item {
    display: block;
    padding: 10px 16px;
    color: var(--text-primary);
    text-decoration: none;
    font-size: 14px;
    transition: background 0.2s ease, color 0.2s ease;
}

.dropdown-item:hover {
    background: var(--primary-color);
    color: white;
}
.mobile-menu-toggle {
            display: none;
            position: fixed;
            top: 15px;
            left: 10px;
            z-index: 1001;
            /* background: var(--primary-color); */
            color: black;
            border: none;
            border-radius: 8px;
            padding: 10px;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .mobile-menu-toggle i {
            font-size: 24px;
        }

        /* Update responsive styles */
        @media (max-width: 1024px) {
            .mobile-menu-toggle {
                display: block;
            }

            .sidebar {
                transform: translateX(-100%);
            }
            
            .main-content {
                margin-left: 0;
            }
            
            .sidebar.active {
                transform: translateX(0);
            }

            /* Add overlay when sidebar is active */
            .sidebar-overlay {
                display: none;
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(0, 0, 0, 0.5);
                z-index: 999;
            }

            .sidebar-overlay.active {
                display: block;
            }

            /* Adjust top bar padding for mobile */
            .top-bar {
                padding-left: 60px;
            }
        }
        
    </style>
</head>
<body>
    <div class="admin-container">
        <!-- Enhanced Sidebar -->
        <button class="mobile-menu-toggle">
            <i class="fas fa-bars-staggered"></i>
        </button>

        <!-- Add overlay div -->
        <div class="sidebar-overlay"></div>
        <aside class="sidebar">
            <div class="sidebar-header">
                <a href="/admin" class="sidebar-brand">
                    <i class="fas fa-court fa-fw"></i>
                    CourtCraft
                </a>
            </div>
            
            <nav class="sidebar-menu">
                <div class="menu-title">Main Menu</div>
                <div class="menu-item">
                    <a href="/admin" class="menu-link <%= path === '/admin' ? 'active' : '' %>">
                        <span class="menu-icon">
                            <i class="fas fa-chart-line"></i>
                        </span>
                        <span class="menu-text">Dashboard</span>
                    </a>
                </div>
                
                <div class="menu-item">
                    <a href="/admin/vendor-requests" class="menu-link <%= path === '/admin/vendor-requests' ? 'active' : '' %>">
                        <span class="menu-icon">
                            <i class="fas fa-user-plus"></i>
                        </span>
                        <span class="menu-text">Vendor Requests</span>
                    </a>
                </div>
                
                <div class="menu-item">
                    <a href="/admin/venues" class="menu-link <%= path === '/admin/venues' ? 'active' : '' %>">
                        <span class="menu-icon">
                            <i class="fas fa-building"></i>
                        </span>
                        <span class="menu-text">All Venues</span>
                    </a>
                </div>
                
                <div class="menu-title">System</div>
                <div class="menu-item">
                    <a href="/admin/notifications" class="menu-link <%= path === '/admin/notifications' ? 'active' : '' %>">
                        <span class="menu-icon">
                            <i class="fas fa-bell"></i>
                        </span>
                        <span class="menu-text">Notifications</span>
                    </a>
                </div>
                
                <div class="menu-item">
                    <a href="/admin/logout" class="menu-link">
                        <span class="menu-icon">
                            <i class="fas fa-sign-out-alt"></i>
                        </span>
                        <span class="menu-text">Logout</span>
                    </a>
                </div>
            </nav>
        </aside>

        <!-- Main Content -->
        <main class="main-content">
            <div class="top-bar">
                <h1 class="page-title"><%= pageTitle %></h1>
                <div class="user-menu">
                    <div class="notifications">
                        <i class="fas fa-bell notification-icon"></i>
                        <span class="notification-badge">3</span>
                    </div>
                    <div class="user-profile">
                        <img src="https://ui-avatars.com/api/?name=Admin&background=0D8ABC&color=fff" alt="Admin" class="user-avatar">
                        <div class="user-info">
                            <div class="user-name">Admin</div>
                            <div class="user-role">Super Admin</div>
                        </div>
                        <div class="dropdown-menu">
                            <a href="/admin/change-password" class="dropdown-item">Change Password</a>
                            <a href="/admin/logout" class="dropdown-item">Logout</a>
                        </div>
                    </div>
                    
                </div>
            </div>

            <div class="content-wrapper">
                <%- body %>
            </div>
        </main>
    </div>
    
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const menuToggle = document.querySelector('.mobile-menu-toggle');
            const sidebar = document.querySelector('.sidebar');
            const overlay = document.querySelector('.sidebar-overlay');
            
            function toggleSidebar() {
                sidebar.classList.toggle('active');
                overlay.classList.toggle('active');
            }

            menuToggle.addEventListener('click', toggleSidebar);
            overlay.addEventListener('click', toggleSidebar);
            
            // Close sidebar when clicking outside on mobile
            document.addEventListener('click', (e) => {
                if (window.innerWidth <= 1024) {
                    if (!sidebar.contains(e.target) && 
                        !menuToggle.contains(e.target) && 
                        sidebar.classList.contains('active')) {
                        toggleSidebar();
                    }
                }
            });

            // Handle window resize
            window.addEventListener('resize', () => {
                if (window.innerWidth > 1024) {
                    sidebar.classList.remove('active');
                    overlay.classList.remove('active');
                }
            });
        });
    </script>
    
</body>
</html>

我已经在仪表板页面上创建了工作正常的页面,并为供应商请求创建了一页,但总是给我错误,我已经验证了很多次以关闭页面

这是供应商请求页面内容:

<%- include('layouts/admin-layout', {
    css: `<link rel="stylesheet" href="/css/vendor-requests.css">`, 
    body: `
        <div class="vendor-requests-container">
            <div class="header">
                <h1>Vendor Requests</h1>
                <p>Manage incoming vendor requests seamlessly</p>
            </div>
            <div id="vendor-requests-list" class="vendor-tiles">
                <%- if (vendorRequests && vendorRequests.length > 0) { %>
                    <% vendorRequests.forEach(function(request) { %>
                        <div class="vendor-tile">
                            <img src="/images/vendor-placeholder.png" alt="Vendor Image" class="vendor-img" />
                            <div class="vendor-info">
                                <h2 class="vendor-name"><%= request.name %></h2>
                                <p class="vendor-email"><%= request.email %></p>
                                <p class="request-date">Request Sent: <%= request.requestDate %></p>
                            </div>
                            <div class="vendor-actions">
                                <button class="action-dots" data-id="<%= request.id %>">⋮</button>
                                <div class="dropdown-menu" id="dropdown-<%= request.id %>">
                                    <button class="dropdown-item btn-details" data-id="<%= request.id %>">View Details</button>
                                    <button class="dropdown-item btn-accept" data-id="<%= request.id %>">Accept</button>
                                    <button class="dropdown-item btn-reject" data-id="<%= request.id %>">Reject</button>
                                </div>
                            </div>
                        </div>
                    <% }) %>
                <% } else { %>
                    <p class="no-requests">No vendor requests available</p>
                <% } %>
            </div>
        </div>

        <script>
            document.addEventListener('click', function(e) {
                if (e.target.classList.contains('action-dots')) {
                    const dropdownId = e.target.dataset.id;
                    document.querySelectorAll('.dropdown-menu').forEach(menu => {
                        if (menu.id === 'dropdown-' + dropdownId) {
                            menu.classList.toggle('show');
                        } else {
                            menu.classList.remove('show');
                        }
                    });
                } else {
                    document.querySelectorAll('.dropdown-menu').forEach(menu => menu.classList.remove('show'));
                }
            });
        </script>
    `
}) %>

现在如果我删除此代码部分:

<div id="vendor-requests-list" class="vendor-tiles">
                <%- if (vendorRequests && vendorRequests.length > 0) { %>
                    <% vendorRequests.forEach(function(request) { %>
                        <div class="vendor-tile">
                            <img src="/images/vendor-placeholder.png" alt="Vendor Image" class="vendor-img" />
                            <div class="vendor-info">
                                <h2 class="vendor-name"><%= request.name %></h2>
                                <p class="vendor-email"><%= request.email %></p>
                                <p class="request-date">Request Sent: <%= request.requestDate %></p>
                            </div>
                            <div class="vendor-actions">
                                <button class="action-dots" data-id="<%= request.id %>">⋮</button>
                                <div class="dropdown-menu" id="dropdown-<%= request.id %>">
                                    <button class="dropdown-item btn-details" data-id="<%= request.id %>">View Details</button>
                                    <button class="dropdown-item btn-accept" data-id="<%= request.id %>">Accept</button>
                                    <button class="dropdown-item btn-reject" data-id="<%= request.id %>">Reject</button>
                                </div>
                            </div>
                        </div>
                    <% }) %>
                <% } else { %>
                    <p class="no-requests">No vendor requests available</p>
                <% } %>
            </div>

视图渲染得很好,但这样总是给我错误:

Could not find matching close tag for "<%-".

任何帮助解决此问题的帮助都将不胜感激

html node.js express syntax ejs
1个回答
0
投票

您的供应商请求页面包含一个 EJS 标签

<%-
,该标签出现在另一个 EJS 标签内的字符串中。 EJS 解析器无法处理此问题,但您可以通过在字符串中将百分号写为
\x25
来规避它。

例如,而不是

<%- "<%- %>" %>

<%- "<\x25- \x25>" %>
© www.soinside.com 2019 - 2024. All rights reserved.