💩 主页数据展示优化

This commit is contained in:
bunny 2025-06-25 20:10:14 +08:00
parent 16991d5b95
commit f8467610f6
3 changed files with 208 additions and 38 deletions

2
.gitignore vendored
View File

@ -12,7 +12,7 @@ dist-ssr
.eslintcache
report.html
vite.config.*.timestamp*
application-prod.yml
bunny-web.site.csr
bunny-web.site.key
bunny-web.site_bundle.crt

View File

@ -3,7 +3,7 @@ server:
spring:
profiles:
active: dev
active: prod
application:
name: generator-code
thymeleaf:

View File

@ -16,6 +16,7 @@
<!-- 加载全局axios配置 -->
<script th:src="@{/lib/js/axios/axios-global.js}"></script>
</head>
<body>
<div id="app">
<div class="container my-4">
@ -39,17 +40,20 @@
</h5>
</div>
<div>
<span class="badge bg-primary rounded-pill me-2">
<i class="bi bi-database me-1"></i>数据库: <span class="fw-normal">{{dbCount}}</span>
</span>
<span class="badge bg-primary rounded-pill me-2">
<i class="bi bi-database me-1"></i>
数据库: <span class="fw-normal">{{databaseList.length}}</span>
</span>
<span class="badge bg-primary rounded-pill">
<i class="bi bi-table me-1"></i>数据库表: <span class="fw-normal">{{tableCount}}</span>
</span>
<i class="bi bi-table me-1"></i>
数据库表: <span class="fw-normal">{{rawTableList.length}}</span>
</span>
</div>
</div>
<p class="card-subtitle mt-2 text-muted">
<i class="bi bi-mouse me-1"></i>点击 <code class="bg-primary bg-opacity-10">表名</code><code
class="bg-primary bg-opacity-10">生成</code> 进行跳转
<i class="bi bi-mouse me-1"></i>
点击 <code class="bg-primary bg-opacity-10">表名</code>
<code class="bg-primary bg-opacity-10">生成</code> 进行跳转
</p>
</div>
@ -58,7 +62,7 @@
<div class="d-flex flex-wrap align-items-center gap-3">
<!-- GitHub 链接 -->
<a class="btn btn-outline-dark d-flex align-items-center gap-2"
href="https://github.com/BunnyMaster/generator-code-server">
href="https://github.com/BunnyMaster/generator-code-server" target="_blank">
<svg class="feather feather-github" fill="none" height="20" stroke="currentColor"
stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"
width="20"
@ -70,7 +74,7 @@
<!-- Gitee 链接 -->
<a class="btn btn-outline-danger d-flex align-items-center gap-2"
href="https://gitee.com/BunnyBoss/generator-code-server">
href="https://gitee.com/BunnyBoss/generator-code-server" target="_blank">
<svg height="20" viewBox="0 0 24 24" width="20" xmlns="http://www.w3.org/2000/svg">
<path d="M11.984 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12a12 12 0 0 0 12-12A12 12 0 0 0 12 0zm6.09 5.333c.328 0 .593.266.592.593v1.482a.594.594 0 0 1-.593.592H9.777c-.982 0-1.778.796-1.778 1.778v5.63c0 .327.266.592.593.592h5.63c.982 0 1.778-.796 1.778-1.778v-.296a.593.593 0 0 0-.592-.593h-4.15a.59.59 0 0 1-.592-.592v-1.482a.593.593 0 0 1 .593-.592h6.815c.327 0 .593.265.593.592v3.408a4 4 0 0 1-4 4H5.926a.593.593 0 0 1-.593-.593V9.778a4.444 4.444 0 0 1 4.445-4.444h8.296Z"
fill="currentColor"/>
@ -101,16 +105,51 @@
<i class="bi bi-table me-1"></i>
数据库表选择
</label>
<input class="form-control shadow-sm" id="tableSelect" v-model="tableSelect"/>
<input class="form-control shadow-sm" id="tableSelect" placeholder="输入表名或表注释"
v-model="tableSelect"/>
</div>
<div class="col-md-2 d-grid">
<button class="btn btn-primary shadow-sm">
<button class="btn btn-primary shadow-sm" disabled type="button"
v-if="dbLoading">
<span aria-hidden="true" class="spinner-grow spinner-grow-sm"></span>
<span role="status">Loading...</span>
</button>
<button @click="getDatabaseInfoMetaData" class="btn btn-primary shadow-sm" v-else>
<i class="bi bi-search me-1"></i>
查询
</button>
</div>
</div>
<div class="pt-1 bg-light">
<a class="d-flex align-items-center text-decoration-none" data-bs-toggle="collapse"
href="#dbInfoCollapse">
<i class="bi bi-database me-2"></i>
<span>数据库连接详情</span>
<i class="bi bi-chevron-down ms-auto"></i>
</a>
<div class="collapse mt-2" id="dbInfoCollapse">
<div class="card card-body bg-white">
<ul class="list-unstyled mb-0">
<li class="mb-2">
<strong>数据库:</strong> {{databaseInfo.databaseProductName}}
{{databaseInfo.databaseProductVersion}}
</li>
<li class="mb-2">
<strong>驱动:</strong> {{databaseInfo.driverName}}
({{databaseInfo.driverVersion}})
</li>
<li class="mb-2"><strong>URL:</strong>
<code class="d-block text-break">{{databaseInfo.url}}</code>
</li>
<li class="mb-2"><strong>用户:</strong> {{databaseInfo.username}}</li>
<li><strong>当前库:</strong> {{databaseInfo.currentDatabase}}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
@ -121,25 +160,34 @@
<i class="bi bi-table me-2"></i>数据表列表
</h5>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<!-- 加载中... -->
<div class="p-5 text-center" v-if="loading">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<!-- 展示当前数据库所有的表 -->
<table class="table table-striped table-bordered table-hover mb-0" v-else>
<thead class="table-light">
<tr>
<th scope="col" width="5%">#</th>
<th scope="col" width="25%">表名</th>
<th scope="col" width="30%">表名</th>
<th scope="col" width="35%">注释</th>
<th scope="col" width="20%">所属数据库</th>
<th scope="col" width="15%">操作</th>
<th class="text-center" scope="col" width="10%">操作</th>
</tr>
</thead>
<tbody>
<tr :key="index" v-for="(table,index) in tableList">
<tr :key="index" v-for="(table,index) in paginatedTableList">
<th scope="row">{{index + 1}}</th>
<td><a class="text-decoration-none" href="#">{{ table.tableName}}</a></td>
<td>{{ table.comment }}</td>
<td>{{ table.tableCat }}</td>
<td>
<td class="text-center">
<button class="btn btn-sm btn-outline-primary">
<i class="bi bi-gear"></i> 生成
</button>
@ -149,64 +197,186 @@
</table>
</div>
</div>
<!-- 在表格显示卡片底部添加分页 -->
<div class="card-footer bg-light">
<div class="d-flex justify-content-between align-items-center">
<div class="form-text">共 {{ totalItems }} 条</div>
<nav aria-label="Page navigation">
<ul class="pagination mb-0">
<li :class="{ disabled: currentPage === 1 }" class="page-item">
<a @click.prevent="currentPage = 1" class="page-link" href="#">
<i class="bi bi-chevron-double-left"></i>
</a>
</li>
<li :class="{ disabled: currentPage === 1 }" class="page-item">
<a @click.prevent="currentPage--" class="page-link" href="#">
<i class="bi bi-chevron-left"></i>
</a>
</li>
<!-- 显示页码 -->
<li :class="{ active: currentPage === page }" :key="page" class="page-item"
v-for="page in visiblePages">
<a @click.prevent="currentPage = page" class="page-link" href="#">{{ page }}</a>
</li>
<li :class="{ disabled: currentPage === totalPages }" class="page-item">
<a @click.prevent="currentPage++" class="page-link" href="#">
<i class="bi bi-chevron-right"></i>
</a>
</li>
<li :class="{ disabled: currentPage === totalPages }" class="page-item">
<a @click.prevent="currentPage = totalPages" class="page-link" href="#">
<i class="bi bi-chevron-double-right"></i>
</a>
</li>
</ul>
</nav>
<div class="dropdown">
<button aria-expanded="false" class="btn btn-outline-secondary dropdown-toggle"
data-bs-toggle="dropdown" id="itemsPerPageDropdown" type="button">
每页 {{ itemsPerPage }} 条
</button>
<ul aria-labelledby="itemsPerPageDropdown" class="dropdown-menu">
<li :key="index" v-for="(table,index) in tablePageOptions">
<a @click.prevent="itemsPerPage = table" class="dropdown-item" href="JavaScript:">
{{table}} 条/页
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
const {createApp, ref} = Vue
createApp({
setup() {
return {
// 数据库个数
dbCount: ref(0),
// 数据库表个数
tableCount: ref(0),
// 数据库选择
dbSelect: ref(""),
// 数据库表过滤
tableSelect: ref(""),
// 所有数据库列表
databaseList: ref([]),
// 数据库信息
databaseInfo: ref({}),
// 数据库表列表
tableList: ref([]),
// 原始数据库列表
rawTableList: ref([]),
// 查询数据库加载
dbLoading: ref(false),
// 是否加载
loading: ref(false),
// 分页相关数据
currentPage: ref(1),
// 每页数
itemsPerPage: ref(10),
// 总的数据条数
totalItems: ref(0),
// 表格选项
tablePageOptions: [5, 10, 20, 50, 100, 150, 200]
};
},
computed: {
// 计算总页数
totalPages() {
return Math.ceil(this.totalItems / this.itemsPerPage);
},
// 分页后的数据
paginatedTableList() {
const start = (this.currentPage - 1) * this.itemsPerPage;
const end = start + this.itemsPerPage;
return this.tableList.slice(start, end);
}
},
methods: {
/* 当前连接的数据库信息 */
async getDatabaseInfoMetaData() {
const response = await axios.get("/table/databaseInfoMetaData")
this.dbLoading = true;
const {data, code} = response.data
if (code !== 200) return
const response = await axios.get("/table/databaseInfoMetaData");
const {data, code} = response.data;
if (code !== 200) return;
// 设置当前数据库有几个
this.dbCount = data.databaseList.length
this.databaseInfo = data
// 设置返回的所有的数据库列表
this.databaseList = data.databaseList
this.databaseList = data.databaseList;
// 设置当前的数据库
this.dbSelect = data.currentDatabase
this.dbSelect = data.currentDatabase;
this.dbLoading = false;
},
/* 获取[当前/所有]数据库表 */
async getDatabaseTableList() {
const response = await axios.get("/table/databaseTableList", {params: {dbName: this.dbSelect}})
this.loading = true;
const {data, code} = response.data
if (code !== 200) return
// 查询数据库表
const response = await axios.get("/table/databaseTableList", {params: {dbName: this.dbSelect}});
const {data, code} = response.data;
if (code !== 200) return;
this.tableList = data
// 设置数据库列表
this.tableList = data;
this.rawTableList = data;
// 更新总条数
this.totalItems = data.length;
// 重置到第一页
this.currentPage = 1;
this.loading = false;
},
/* 计算可见的页码范围 */
visiblePages() {
// 显示当前页前后各2页
const range = 2;
const start = Math.max(1, this.currentPage - range);
const end = Math.min(this.totalPages, this.currentPage + range);
const pages = [];
for (let i = start; i <= end; i++) {
pages.push(i);
}
return pages;
}
},
async mounted() {
mounted() {
// 当前连接的数据库信息
await this.getDatabaseInfoMetaData()
// 获取[当前/所有]数据库表
await this.getDatabaseTableList()
this.getDatabaseInfoMetaData();
},
watch: {
/* 数据表选择 */
dbSelect: {
handler() {
this.getDatabaseTableList();
}
},
/* 过滤数据表 */
tableSelect: {
handler(val) {
this.tableList = this.rawTableList;
// 根据表名进行过滤筛选或者根据注释内容进行筛选
this.tableList = this.tableList.filter(table => table.tableName.includes(val) || table.comment.includes(val));
}
}
}
}).mount('#app')
}).mount('#app');
</script>
</html>