| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>用户管理系统</title>
- <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
- </head>
- <body>
- <div id="app" class="container mt-4">
- <h1 class="mb-4">用户管理系统</h1>
-
- <!-- 查询表单 -->
- <div class="card mb-4">
- <div class="card-header">
- <h5 class="mb-0">查询用户</h5>
- </div>
- <div class="card-body">
- <form @submit.prevent="searchUsers" class="row g-3">
- <div class="col-md-4">
- <label class="form-label">账号</label>
- <input type="text" class="form-control" v-model="searchParams.passport" placeholder="输入账号">
- </div>
- <div class="col-md-4">
- <label class="form-label">昵称</label>
- <input type="text" class="form-control" v-model="searchParams.nickname" placeholder="输入昵称">
- </div>
- <div class="col-md-4">
- <label class="form-label">每页数量</label>
- <select class="form-select" v-model="searchParams.pageSize">
- <option value="10">10</option>
- <option value="20">20</option>
- <option value="50">50</option>
- </select>
- </div>
- <div class="col-12">
- <button type="submit" class="btn btn-primary">查询</button>
- <button type="button" class="btn btn-secondary ms-2" @click="resetSearch">重置</button>
- </div>
- </form>
- </div>
- </div>
- <!-- 用户列表 -->
- <div class="card">
- <div class="card-header d-flex justify-content-between align-items-center">
- <h5 class="mb-0">用户列表</h5>
- <span class="text-muted">共 {{ total }} 条记录</span>
- </div>
- <div class="card-body">
- <div class="table-responsive">
- <table class="table table-striped table-hover">
- <thead>
- <tr>
- <th>ID</th>
- <th>账号</th>
- <th>昵称</th>
- <th>创建时间</th>
- <th>更新时间</th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="user in userList" :key="user.id">
- <td>{{ user.id }}</td>
- <td>{{ user.passport }}</td>
- <td>{{ user.nickname }}</td>
- <td>{{ user.created_at }}</td>
- <td>{{ user.updated_at }}</td>
- </tr>
- <tr v-if="userList.length === 0">
- <td colspan="5" class="text-center text-muted">暂无数据</td>
- </tr>
- </tbody>
- </table>
- </div>
-
- <!-- 分页 -->
- <nav v-if="total > 0">
- <ul class="pagination justify-content-center">
- <li class="page-item" :class="{ disabled: currentPage === 1 }">
- <a class="page-link" href="#" @click.prevent="changePage(currentPage - 1)">上一页</a>
- </li>
- <li class="page-item" v-for="page in pages" :key="page" :class="{ active: page === currentPage }">
- <a class="page-link" href="#" @click.prevent="changePage(page)">{{ page }}</a>
- </li>
- <li class="page-item" :class="{ disabled: currentPage === totalPages }">
- <a class="page-link" href="#" @click.prevent="changePage(currentPage + 1)">下一页</a>
- </li>
- </ul>
- </nav>
- </div>
- </div>
- </div>
- <script>
- const { createApp, ref, computed, onMounted } = Vue;
-
- createApp({
- setup() {
- const userList = ref([]);
- const total = ref(0);
- const currentPage = ref(1);
- const pageSize = ref(10);
- const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
-
- const searchParams = ref({
- passport: '',
- nickname: '',
- pageSize: 10
- });
-
- const pages = computed(() => {
- const result = [];
- const start = Math.max(1, currentPage.value - 2);
- const end = Math.min(totalPages.value, start + 4);
-
- for (let i = start; i <= end; i++) {
- result.push(i);
- }
- return result;
- });
-
- async function fetchUsers(page = 1) {
- try {
- const params = new URLSearchParams({
- page: page,
- pageSize: searchParams.value.pageSize,
- passport: searchParams.value.passport,
- nickname: searchParams.value.nickname
- });
-
- const response = await fetch(`/user/list?${params}`);
- const data = await response.json();
-
- if (data.code === 0) {
- userList.value = data.data.list;
- total.value = data.data.total;
- currentPage.value = data.data.page;
- pageSize.value = searchParams.value.pageSize;
- } else {
- alert('获取用户列表失败: ' + data.message);
- }
- } catch (error) {
- console.error('Error:', error);
- alert('网络错误,请稍后重试');
- }
- }
-
- function searchUsers() {
- currentPage.value = 1;
- fetchUsers(1);
- }
-
- function resetSearch() {
- searchParams.value = {
- passport: '',
- nickname: '',
- pageSize: 10
- };
- searchUsers();
- }
-
- function changePage(page) {
- if (page < 1 || page > totalPages.value) return;
- fetchUsers(page);
- }
-
- onMounted(() => {
- fetchUsers(1);
- });
-
- return {
- userList,
- total,
- currentPage,
- totalPages,
- pages,
- searchParams,
- searchUsers,
- resetSearch,
- changePage
- };
- }
- }).mount('#app');
- </script>
- </body>
- </html>
|