一个不错的html渲染页面模板

This commit is contained in:
2025-11-25 22:55:53 +08:00
parent adbe4a990d
commit e6ce15f66b
6 changed files with 213 additions and 96 deletions

43
main.go
View File

@@ -1,23 +1,52 @@
package main package main
import ( import (
"html/template"
"time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// Article 文章结构体,用于存储文章相关信息
type Article struct { type Article struct {
Title string Title string // 文章标题
Content string Content string // 文章内容
} }
// UnixToTime 将Unix时间戳转换为格式化的日期时间字符串
// 参数:
//
// timestamp: Unix时间戳
//
// 返回值:
//
// 格式化后的日期时间字符串,格式为"2006-01-02 15:04:05"
func UnixToTime(timestamp int) string {
t := time.Unix(int64(timestamp), 0)
return t.Format("2006-01-02 15:04:05")
}
// main 函数是程序的入口点初始化并启动Web服务器
func main() { func main() {
// 创建默认的gin引擎
r := gin.Default() r := gin.Default()
// 加载模板(支持多层目录)
// 注册模板函数使模板可以使用自定义函数UnixToTime
r.SetFuncMap(template.FuncMap{
"UnixToTime": UnixToTime,
})
// 加载模板文件,支持多层目录结构
r.LoadHTMLGlob("templates/**/*") r.LoadHTMLGlob("templates/**/*")
// 配置静态文件目录,将./static目录映射到URL路径/static
r.Static("/static", "./static") r.Static("/static", "./static")
// 路由 // 设置路由
// 根路由处理函数,渲染首页
r.GET("/", func(c *gin.Context) { r.GET("/", func(c *gin.Context) {
c.HTML(200, "pages/index.html", gin.H{ // 渲染pages/index.html模板并传递数据
c.HTML(200, "pages/index", gin.H{
"title": "Main website", "title": "Main website",
"score": 60, "score": 60,
"hobby": []string{"吃饭", "睡觉", "打豆豆"}, "hobby": []string{"吃饭", "睡觉", "打豆豆"},
@@ -37,10 +66,12 @@ func main() {
Title: "标题", Title: "标题",
Content: "测试2", Content: "测试2",
}, },
"data": 1764077331, // Unix时间戳示例
}) })
}) })
err := r.Run(":8080") // 启动HTTP服务器监听在8081端口
err := r.Run(":8081")
if err != nil { if err != nil {
return return
} }

135
static/navbar.css Normal file
View File

@@ -0,0 +1,135 @@
/*
* navbar.css - 网站导航栏样式文件
* 负责定义网站的导航栏和主内容区域的基本样式
*/
/*
* 全局样式设置
* 重置浏览器默认边距,设置全局字体和背景色
*/
body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
background: #f4f6f9;
color: #333;
/* 为固定导航栏留出顶部空间 */
padding-top: 70px; /* 大于或等于导航栏高度 */
}
/*
* 导航栏容器样式
* 使用flex布局实现两端对齐的导航栏应用渐变背景和阴影效果
* 添加position: fixed使其固定在页面顶部
*/
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(90deg, #1e3c72, #2a5298);
padding: 0.8rem 2rem;
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
/* 固定定位相关样式 */
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000; /* 确保导航栏在其他元素之上 */
}
/*
* 网站Logo样式
* 设置Logo字体大小、粗细和颜色添加悬停动画效果
*/
.navbar .logo {
font-size: 1.5rem;
font-weight: bold;
color: #fff;
letter-spacing: 2px;
transition: transform 0.3s ease;
}
/*
* Logo悬停效果
* 鼠标悬停时放大并轻微旋转Logo
*/
.navbar .logo:hover {
transform: scale(1.1) rotate(-3deg);
}
/*
* 导航链接列表样式
* 移除默认列表样式使用flex布局排列导航项
*/
.nav-links {
list-style: none;
display: flex;
gap: 1.5rem;
}
/*
* 导航链接样式
* 移除下划线,设置文字颜色和粗细,为动画效果做准备
*/
.nav-links li a {
text-decoration: none;
color: #fff;
font-weight: 500;
position: relative;
transition: color 0.3s ease;
}
/*
* 导航链接下划线效果
* 使用伪元素创建底部横线初始宽度为0
*/
.nav-links li a::after {
content: "";
position: absolute;
width: 0;
height: 2px;
bottom: -4px;
left: 0;
background-color: #ffcc00;
transition: width 0.3s ease;
}
/*
* 导航链接悬停文字颜色变化
* 鼠标悬停时文字变为金色
*/
.nav-links li a:hover {
color: #ffcc00;
}
/*
* 导航链接下划线动画
* 鼠标悬停时底部横线从0扩展到100%宽度
*/
.nav-links li a:hover::after {
width: 100%;
}
/*
* 主内容区域样式
* 设置主内容区域的内边距
*/
main {
padding: 2rem;
}
/*
* 主内容区域标题样式
* 设置主内容区域中标题的颜色
*/
main h1, main h2 {
color: #2a5298;
}
/*
* 主内容区域段落样式
* 设置主内容区域中段落的行高
*/
main p {
line-height: 1.6;
}

View File

@@ -1,65 +0,0 @@
body {
margin: 0;
font-family: "Segoe UI", Arial, sans-serif;
background: #f4f6f9;
color: #333;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(90deg, #1e3c72, #2a5298);
padding: 0.8rem 2rem;
box-shadow: 0 4px 10px rgba(0,0,0,0.3);
}
.navbar .logo {
font-size: 1.5rem;
font-weight: bold;
color: #fff;
letter-spacing: 2px;
transition: transform 0.3s ease;
}
.navbar .logo:hover {
transform: scale(1.1) rotate(-3deg);
}
.nav-links {
list-style: none;
display: flex;
gap: 1.5rem;
}
.nav-links li a {
text-decoration: none;
color: #fff;
font-weight: 500;
position: relative;
transition: color 0.3s ease;
}
.nav-links li a::after {
content: "";
position: absolute;
width: 0%;
height: 2px;
bottom: -4px;
left: 0;
background-color: #ffcc00;
transition: width 0.3s ease;
}
.nav-links li a:hover {
color: #ffcc00;
}
.nav-links li a:hover::after {
width: 100%;
}
main {
padding: 2rem;
}
main h1, main h2 {
color: #2a5298;
}
main p {
line-height: 1.6;
}

View File

@@ -1,14 +1,19 @@
{{ define "base" }} {{/* 定义基础模板,作为其他页面模板的布局基础 */}}
{{ define "layout/base" }}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh"> <html lang="zh">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
{{/* 标题块定义 - 允许子模板重写标题内容 */}}
<title>{{ block "title" . }}默认标题{{ end }}</title> <title>{{ block "title" . }}默认标题{{ end }}</title>
{{/* 引入静态样式文件 */}}
<link rel="stylesheet" href="/static/style.css"> <link rel="stylesheet" href="/static/style.css">
</head> </head>
<body> <body>
{{/* 引入导航栏模板 */}}
{{ template "navbar" . }} {{ template "navbar" . }}
{{/* 主内容区域定义 - 子模板应在此处填充具体内容 */}}
<main> <main>
{{ block "content" . }}{{ end }} {{ block "content" . }}{{ end }}
</main> </main>

View File

@@ -1,6 +1,12 @@
{{ define "navbar" }} {{/* 定义导航栏模板,包含网站导航链接 */}}
{{ define "layout/navbar" }}
<link rel="stylesheet" href="/static/navbar.css">
<nav class="navbar"> <nav class="navbar">
{{/* 网站Logo区域 */}}
<div class="logo">🔥 MyGinSite</div> <div class="logo">🔥 MyGinSite</div>
{{/* 导航链接列表 */}}
<ul class="nav-links"> <ul class="nav-links">
<li><a href="/">首页</a></li> <li><a href="/">首页</a></li>
<li><a href="/about">关于我们</a></li> <li><a href="/about">关于我们</a></li>

View File

@@ -1,4 +1,5 @@
{{define "pages/index.html"}} {{/* 定义index页面模板 */}}
{{define "pages/index"}}
<!doctype html> <!doctype html>
<html lang="zh"> <html lang="zh">
<head> <head>
@@ -7,50 +8,54 @@
<title>{{.title}}</title> <title>{{.title}}</title>
</head> </head>
<body> <body>
{{/*输出*/}} {{template "layout/navbar"}}
{{/* 基本数据输出示例 - 直接渲染标题变量 */}}
<h2>{{.title}}</h2> <h2>{{.title}}</h2>
{{/*定义变量*/}} {{/* 模板变量定义示例 - 将标题赋值给局部变量t */}}
{{$t := .title}} {{$t := .title}}
<h4>{{$t}}</h4> <h4>{{$t}}</h4>
{{/* 条件判断示例 - 根据score值判断是否及格 */}}
{{/*条件判断*/}} {{if ge .score 60}} <!-- ge: 大于等于 -->
{{if ge .score 60}}
<p>及格</p> <p>及格</p>
{{else}} {{else}}
<P></P> <p></p>
{{end}} {{end}}
{{/*循环遍历数据*/}} {{/* 简单数组循环遍历示例 */}}
{{range $key, $value := .hobby}} <!-- 遍历爱好列表 -->
{{range $key,$value:=.hobby}}
<ul> <ul>
<li>{{$key}}--{{$value}}</li> <li>{{$key}}--{{$value}}</li> <!-- 输出索引和值 -->
</ul> </ul>
{{end}} {{end}}
{{range $key,$value:=.newsList}} {{/* 结构体数组循环遍历示例 */}}
{{range $key, $value := .newsList}} <!-- 遍历文章列表 -->
<ul> <ul>
<li>{{$key}}--{{$value.Title}}--{{$value.Content}}</li> <li>{{$key}}--{{$value.Title}}--{{$value.Content}}</li> <!-- 输出索引和文章属性 -->
</ul> </ul>
{{end}} {{end}}
{{/* 空数组处理示例 - 当newsList2为空时显示提示信息 */}}
{{range $key, $value := .newsList2}} {{range $key, $value := .newsList2}}
<ul> <ul>
<li>{{$key}}--{{$value.Title}}--{{$value.Content}}</li> <li>{{$key}}--{{$value.Title}}--{{$value.Content}}</li>
</ul> </ul>
{{else}} {{else}}
<li>没有数据</li> <li>没有数据</li> <!-- 当数组为空时执行 -->
{{end}} {{end}}
{{/*结构结构*/}} {{/* 结构体数据访问示例 - 使用with语句简化结构体属性访问 */}}
{{with .news}} {{with .news}} <!-- 针对news结构体设置上下文 -->
{{.Title}} {{.Title}} <!-- 直接访问Title属性等同于.news.Title -->
{{.Content}} {{.Content}} <!-- 直接访问Content属性等同于.news.Content -->
{{end}} {{end}}
<br>
{{/* 自定义模板函数使用示例 */}}
{{.data}} <!-- 输出原始时间戳 -->
{{UnixToTime .data}} <!-- 使用自定义函数将时间戳转换为格式化日期 -->
</body> </body>
</html> </html>
{{end}} {{end}}