Files
PR-Helper/templates/layouts/base.html
T

83 lines
3.9 KiB
HTML
Raw Normal View History

{{define "head"}}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PR-Helper</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="/static/css/style.css">
<script src="/static/js/htmx.min.js"></script>
<style>
.toast-enter { transform: translateX(100%); opacity: 0; }
.toast-active { transform: translateX(0); opacity: 1; transition: transform 0.3s ease, opacity 0.3s ease; }
.toast-exit { transform: translateX(100%); opacity: 0; transition: transform 0.3s ease, opacity 0.3s ease; }
</style>
<script>
// Global toast notification system
(function() {
function ensureContainer() {
var c = document.getElementById('toast-container');
if (!c) {
c = document.createElement('div');
c.id = 'toast-container';
c.className = 'fixed top-4 right-4 z-50 flex flex-col items-end space-y-2';
document.body.appendChild(c);
}
return c;
}
window.showToast = function(message, type) {
type = type || 'info';
var colors = {
success: 'bg-green-50 border-green-200 text-green-800',
error: 'bg-red-50 border-red-200 text-red-800',
info: 'bg-blue-50 border-blue-200 text-blue-800',
warning: 'bg-yellow-50 border-yellow-200 text-yellow-800'
};
var icons = { success: '✓', error: '✗', info: 'ℹ', warning: '⚠' };
var container = ensureContainer();
var el = document.createElement('div');
el.className = 'px-4 py-3 rounded-md border text-sm shadow-lg max-w-sm toast-enter ' + (colors[type] || colors.info);
el.innerHTML = '<span class="mr-2 font-bold">' + (icons[type] || icons.info) + '</span>' +
'<span>' + message + '</span>' +
'<button onclick="this.parentElement.remove()" class="ml-3 text-current opacity-50 hover:opacity-100">&times;</button>';
container.appendChild(el);
requestAnimationFrame(function() { el.className = el.className.replace('toast-enter', 'toast-active'); });
setTimeout(function() {
el.className = el.className.replace('toast-active', 'toast-exit');
setTimeout(function() { el.remove(); }, 300);
}, 4000);
};
})();
</script>
</head>
{{end}}
{{define "nav"}}
<nav class="bg-white shadow-sm border-b border-gray-200">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-14">
<div class="flex items-center space-x-8">
<a href="/" class="text-lg font-bold text-indigo-600 hover:text-indigo-700">🔀 PR-Helper</a>
<a href="/" class="text-sm text-gray-600 hover:text-gray-900">首页</a>
<a href="/settings" class="text-sm text-gray-600 hover:text-gray-900">设置</a>
</div>
<div class="flex items-center space-x-4">
{{if .User}}
<span class="text-sm text-gray-500">{{.User.Email}}</span>
<form method="POST" action="/api/auth/logout" class="inline">
<button type="submit" class="text-sm text-gray-500 hover:text-gray-700">退出</button>
</form>
{{end}}
</div>
</div>
</div>
</nav>
{{end}}
{{define "footer"}}
<footer class="bg-white border-t border-gray-200 py-4">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center text-sm text-gray-400">
PR-Helper — AI 驱动的 PR 描述与代码审查
</div>
</footer>
{{end}}