SpringBoot3+Vue3 实现前台首页的设计

做页面最重要的东西有哪些?

做一个页面,只需要考虑两个东西:布局和样式,比如说你要画一个人面像,要先画轮廓,简单的勾勒一下大概一些元素的位置(布局),然后再针对具体的位置,我们去画鼻子画眼睛(样式)

1.1 布局

  1. elementplus里面的行列布局 : el-row 和 el-row的布局
  2. flex布局
1
style="display: flex;align-items: center;justify-content: center"

常见的布局有哪些?一般是图文并茂,比如宫格(上下) 宫格(左右)

1.2 样式

字体大小:font-size

字体颜色: color

字体粗细: font-weight

外边边距,内边距: margin,padding

背景颜色 宽高,行高 边: background-color ,width,height ,line-height, border

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<template>
<div style="background-color: #f3ecf1;min-height: 1000px;">
<el-menu
:default-active="1"
class="el-menu-demo"
mode="horizontal"
>
<el-menu-item index="1">系统首页</el-menu-item>
<el-menu-item @click="logout">退出</el-menu-item>
</el-menu>
<!-- 上下 -->
<div style="width: 80%;margin: 20px auto">
<div style="font-size: 18px;border-left: 7px solid #55ff00;padding-left: 5px;height: 30px;line-height: 30px;">旅游攻略</div>
<div style="margin-top: 20px">
<el-row gutter="10">
<el-col v-for="item in data.introductionData" :span="6" style="margin-bottom: 5px">
<img :src="item.img" alt="" style="width: 100%;height: 310px;border-radius: 5px">
<div style="font-size: 18px;font-weight: bold;line-height: 30px; height: 30px">{{item.title}}</div>
<div style="display: flex;align-items: center;justify-content: center;margin-top:10px;grid-gap: 10px ">
<img :src="item.userAvatar" alt="" style="width: 30px;height: 30px;border-radius: 50%">
<div style="font-size: 15px">{{item.username}}</div>
<div style="color: #666">{{item.time}}</div>
</div>
</el-col>
</el-row>
</div>

</div>

<!--左右 -->
<div style="width: 80%;margin: 20px auto">
<div style="font-size: 20px;border-left: 7px solid #55ff00;padding-left: 5px;height: 30px;line-height: 30px;">旅游攻略</div>
<div style="display: flex;margin-top: 20px;height: 300px" v-for="item in data.introductionData">
<div style="flex: 1;">
<img :src="item.img" alt="" style="width: 100%;height: 250px;display: block">
</div>
<div style="flex: 3;width: 100%;">
<div>{{item.title}}</div>
<!-- min-width: 0 允许子元素收缩 -->
<div class="line4">{{item.content}}</div>
</div>
</div>
</div>

<!-- 强制内容超过 4 行 -->
<!-- 测试区域 -->
<div style="width: 300px; background: #fff; margin: 20px auto;">
<div class="line4" style="line-height: 1.5;">
{{ "这是一段很长的内容".repeat(20) }}
</div>
</div>
</div>
</template>

<script setup>

import {reactive} from "vue";
import request from "@/utils/request.js";
import {ElMessage} from "element-plus";

const data = reactive({
user: JSON.parse(localStorage.getItem('code2025_user') || "{}"),
introductionData: [],
})

const loadIntroduction = () => {
request.get('introduction/selectAll').then(res => {
if(res.code === '200'){
data.introductionData = res.data
}else{
ElMessage.error(res.msg)
}
})
}
loadIntroduction()

const logout = () => {
localStorage.removeItem("code2025_user")
location.href = '/login'
}
</script>


<style>
.line4 {
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 4;
overflow: hidden;
line-height: 1.5; /* 确保行高一致 */
max-height: calc(1.5em * 4); /* 强制最大高度为4行 */
}
</style>

image-20250308184945346.png

怎么改?

在Introduction中新增字段:

1
private String description;

在service:

1
2
3
4
5
6
7
public List<Introduction> selectAll(Introduction introduction){
List<Introduction> introductions = introductionMapper.selectAll(introduction);
for (Introduction dbIntroduction : introductions) {
dbIntroduction.setDescription(HtmlUtil.cleanHtmlTag(dbIntroduction.getContent()));
}
return introductions;
}

然后展示description

1
<div class="line4">{{item.description}}</div>

完整页面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
<template>
<div style="background-color: #f3ecf1;height: auto;">
<el-menu :default-active="1" class="el-menu-demo" mode="horizontal">
<el-menu-item index="1">系统首页</el-menu-item>
<el-menu-item @click="logout">退出</el-menu-item>
</el-menu>

<!-- 上下布局 -->
<div style="width: 80%;margin: 20px auto">
<div style="font-size: 18px;border-left: 7px solid #55ff00;padding-left: 5px;height: 30px;line-height: 30px;">
旅游攻略
</div>
<div style="margin-top: 20px">
<el-row :gutter="10">
<el-col v-for="item in data.introductionData" :key="item.id" :span="6" style="margin-bottom: 5px">
<img :src="item.img" alt="" style="width: 100%;height: 310px;border-radius: 5px">
<div style="font-size: 18px;font-weight: bold;line-height: 30px;height: 30px">{{ item.title }}</div>
<div style="display: flex;align-items: center;justify-content: center;margin-top:10px;gap: 10px">
<img :src="item.userAvatar" alt="" style="width: 30px;height: 30px;border-radius: 50%">
<div style="font-size: 15px">{{ item.username }}</div>
<div style="color: #666">{{ item.time }}</div>
</div>
</el-col>
</el-row>
</div>
</div>

<!-- 左右布局 -->
<div style="width: 80%;margin: 20px auto">
<div style="font-size: 20px;border-left: 7px solid #55ff00;padding-left: 5px;height: 30px;line-height: 30px;">
旅游攻略
</div>
<div v-for="item in data.introductionData" :key="item.id"
style="display: flex; margin-top: 20px; gap: 20px; height: auto;">

<!-- 左侧图片 -->
<div style="flex: 1; min-width: 0;">
<img :src="item.img" alt="" style="width: 100%;height: 250px;display: block;border-radius: 5px">
</div>

<!-- 右侧内容 -->
<div style="flex: 3; min-width: 0;">
<div style="font-size: 20px;font-weight: bold;">{{ item.title }}</div>
<div class="line5" style="margin-top: 10px;font-size: 15px;color: #666;line-height: 1.5;text-align: center">
{{ item.description }}
</div>
<!-- 用户信息左对齐 -->
<div style="display: flex; align-items: center; justify-content: flex-start; gap: 10px; margin-top: 10px;">
<img :src="item.userAvatar" alt="" style="width: 30px;height: 30px;border-radius: 50%">
<div style="font-size: 15px">{{ item.username }}</div>
<div style="color: #666">{{ item.time }}</div>
</div>
</div>
</div>
</div>

<!-- &lt;!&ndash; 测试区域(取消注释验证) &ndash;&gt;-->
<!-- <div style="width: 300px; background: #fff; margin: 20px auto;">-->
<!-- <div class="line5" style="line-height: 1.5;">-->
<!-- {{ "这是一段很长的内容".repeat(30) }}-->
<!-- </div>-->
<!-- </div>-->
</div>
</template>

<script setup>
import { reactive } from "vue";
import request from "@/utils/request.js";
import { ElMessage } from "element-plus";

const data = reactive({
user: JSON.parse(localStorage.getItem('code2025_user') || "{}"),
introductionData: [],
});

const loadIntroduction = () => {
request.get('introduction/selectAll').then(res => {
if (res.code === '200') {
data.introductionData = res.data;
} else {
ElMessage.error(res.msg);
}
});
};
loadIntroduction();

const logout = () => {
localStorage.removeItem("code2025_user");
location.href = '/login';
};
</script>

<style>
.line5 {
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 5;
overflow: hidden;
line-height: 1.5;
max-height: calc(1.5em * 5);
}
</style>

轮播图和详情页设计

1.轮播图怎么做?

ElmentPlus 叫走马灯

有分静态和动态

静态:

1
2
3
4
5
6
7
<div style="margin-bottom: 20px">
<el-carousel height="350px">
<el-carousel-item v-for="item in data.carouseData" :key="item">
<img :src="item" alt="" style="height: 600px;width: 100%">
</el-carousel-item>
</el-carousel>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { reactive } from "vue";
import request from "@/utils/request.js";
import { ElMessage } from "element-plus";
import lun1 from "@/assets/imgs/lun1.png"
import lun2 from "@/assets/imgs/lun2.png"
import lun3 from "@/assets/imgs/lun3.png"
import lun4 from "@/assets/imgs/lun4.png"

const data = reactive({
user: JSON.parse(localStorage.getItem('code2025_user') || "{}"),
introductionData: [],
carouseData: [lun1,lun2,lun3,lun4]
});

动态:

可以在文章中加多一个字段用作轮播图图片,点击就可以进去查看

1
2
3
4
5
6
7
8
<div style="margin-bottom: 20px">
<el-carousel height="350px">
<el-carousel-item v-for="item in data.introductionData" :key="item">
<img :src="item.img" alt="" style="height: 600px;width: 100%">
</el-carousel-item>
</el-carousel>

</div>

做详情页:

详情页的设计:

1
2
3
<div style="flex: 1; min-width: 0;">
<img @click="navTo('/font/introductionDetail?id='+item.id)" :src="item.img" alt="" style="width: 100%;height: 250px;display: block;border-radius: 5px;cursor: pointer">
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div style="width: 70%;margin: 20px auto">
<div style="text-align: center;font-weight: bold;font-size: 20px">{{data.introductionData.title}}</div>



</div>
</template>

<script setup>

import {reactive} from "vue";
import router from "@/router/index.js";
import request from "@/utils/request.js";
import {ElMessage} from "element-plus";

const data = reactive({
user: JSON.parse(localStorage.getItem('code2025_user') || "{}"),
introductionId: router.currentRoute.value.query.id,
introductionData: {}
})

const loadIntroduction = () =>{
// console.log(data.introductionId)
request.get("/introduction/selectById/"+data.introductionId).then(res=>{
if(res.code === '200'){
data.introductionData = res.data
}else{
ElMessage.error(res.msg)
}
})
}
loadIntroduction()
</script>