阶段四:前端开发 - 管理后台 (worklog-web): Vue 3 + Element Plus - 登录页面、主布局、人员管理、模板管理、工作日志 - baseURL: /wladmin/api/v1 - 移动端 H5 (worklog-mobile): Vue 3 + Vant 4 - 登录、首页、日志列表、新建/编辑/详情页 - baseURL: /wlmobile/api/v1 阶段五:部署准备 - 后端打包: worklog-api-1.0.0.jar (48MB) - 前端打包: worklog-web (1.6MB), worklog-mobile (632KB) - 单元测试: 29个测试全部通过 - API端口调整为 8200 - Nginx配置更新 配置变更 - 后端端口: 8080 → 8200 - 前端 baseURL: /wlog → /wladmin, /wlmobile - Nginx 代理路径更新
299 lines
8.6 KiB
Vue
299 lines
8.6 KiB
Vue
<template>
|
|
<div class="user-page">
|
|
<el-card>
|
|
<!-- 搜索栏 -->
|
|
<el-form :inline="true" :model="searchForm" class="search-form">
|
|
<el-form-item label="姓名">
|
|
<el-input v-model="searchForm.name" placeholder="请输入姓名" clearable />
|
|
</el-form-item>
|
|
<el-form-item label="账号">
|
|
<el-input v-model="searchForm.username" placeholder="请输入账号" clearable />
|
|
</el-form-item>
|
|
<el-form-item label="状态">
|
|
<el-select v-model="searchForm.status" placeholder="请选择" clearable>
|
|
<el-option label="启用" :value="1" />
|
|
<el-option label="禁用" :value="0" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
|
<el-button @click="handleReset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<!-- 工具栏 -->
|
|
<el-row class="toolbar" justify="space-between">
|
|
<el-col :span="12">
|
|
<el-button type="primary" @click="handleAdd">新增用户</el-button>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<!-- 表格 -->
|
|
<el-table :data="tableData" v-loading="loading" stripe>
|
|
<el-table-column prop="username" label="账号" width="120" />
|
|
<el-table-column prop="name" label="姓名" width="120" />
|
|
<el-table-column prop="phone" label="联系方式" width="130" />
|
|
<el-table-column prop="email" label="邮箱" width="180" />
|
|
<el-table-column prop="position" label="职位" width="120" />
|
|
<el-table-column prop="role" label="角色" width="100">
|
|
<template #default="{ row }">
|
|
<el-tag :type="row.role === 'ADMIN' ? 'danger' : 'info'">
|
|
{{ row.role === 'ADMIN' ? '管理员' : '普通用户' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="status" label="状态" width="80">
|
|
<template #default="{ row }">
|
|
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
|
|
{{ row.status === 1 ? '启用' : '禁用' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="createdTime" label="创建时间" width="180" />
|
|
<el-table-column label="操作" fixed="right" width="200">
|
|
<template #default="{ row }">
|
|
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
|
|
<el-button
|
|
type="primary"
|
|
link
|
|
@click="handleStatus(row)"
|
|
v-if="row.role !== 'ADMIN'"
|
|
>
|
|
{{ row.status === 1 ? '禁用' : '启用' }}
|
|
</el-button>
|
|
<el-button
|
|
type="danger"
|
|
link
|
|
@click="handleDelete(row)"
|
|
v-if="row.role !== 'ADMIN'"
|
|
>
|
|
删除
|
|
</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页 -->
|
|
<el-pagination
|
|
v-model:current-page="pageNum"
|
|
v-model:page-size="pageSize"
|
|
:total="total"
|
|
:page-sizes="[10, 20, 50]"
|
|
layout="total, sizes, prev, pager, next"
|
|
@size-change="handleSearch"
|
|
@current-change="handleSearch"
|
|
class="pagination"
|
|
/>
|
|
</el-card>
|
|
|
|
<!-- 新增/编辑对话框 -->
|
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="80px">
|
|
<el-form-item label="账号" prop="username" v-if="!form.id">
|
|
<el-input v-model="form.username" placeholder="请输入账号" />
|
|
</el-form-item>
|
|
<el-form-item label="密码" prop="password" v-if="!form.id">
|
|
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
|
|
</el-form-item>
|
|
<el-form-item label="姓名" prop="name">
|
|
<el-input v-model="form.name" placeholder="请输入姓名" />
|
|
</el-form-item>
|
|
<el-form-item label="联系方式">
|
|
<el-input v-model="form.phone" placeholder="请输入联系方式" />
|
|
</el-form-item>
|
|
<el-form-item label="邮箱">
|
|
<el-input v-model="form.email" placeholder="请输入邮箱" />
|
|
</el-form-item>
|
|
<el-form-item label="职位">
|
|
<el-input v-model="form.position" placeholder="请输入职位" />
|
|
</el-form-item>
|
|
<el-form-item label="角色" v-if="!form.id">
|
|
<el-select v-model="form.role" placeholder="请选择角色">
|
|
<el-option label="普通用户" value="USER" />
|
|
<el-option label="管理员" value="ADMIN" />
|
|
</el-select>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, reactive, computed } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import { pageUsers, createUser, updateUser, updateUserStatus, deleteUser } from '@/api/user'
|
|
import type { User } from '@/api/user'
|
|
import type { FormInstance, FormRules } from 'element-plus'
|
|
|
|
const loading = ref(false)
|
|
const submitLoading = ref(false)
|
|
const tableData = ref<User[]>([])
|
|
const total = ref(0)
|
|
const pageNum = ref(1)
|
|
const pageSize = ref(10)
|
|
|
|
const searchForm = reactive({
|
|
name: '',
|
|
username: '',
|
|
status: undefined as number | undefined
|
|
})
|
|
|
|
const dialogVisible = ref(false)
|
|
const formRef = ref<FormInstance>()
|
|
const form = reactive({
|
|
id: '',
|
|
username: '',
|
|
password: '',
|
|
name: '',
|
|
phone: '',
|
|
email: '',
|
|
position: '',
|
|
role: 'USER'
|
|
})
|
|
|
|
const dialogTitle = computed(() => form.id ? '编辑用户' : '新增用户')
|
|
|
|
const rules: FormRules = {
|
|
username: [{ required: true, message: '请输入账号', trigger: 'blur' }],
|
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
|
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
|
|
}
|
|
|
|
// 加载数据
|
|
async function loadData() {
|
|
loading.value = true
|
|
try {
|
|
const result = await pageUsers({
|
|
pageNum: pageNum.value,
|
|
pageSize: pageSize.value,
|
|
...searchForm
|
|
})
|
|
tableData.value = result.list
|
|
total.value = result.total
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 搜索
|
|
function handleSearch() {
|
|
pageNum.value = 1
|
|
loadData()
|
|
}
|
|
|
|
// 重置
|
|
function handleReset() {
|
|
searchForm.name = ''
|
|
searchForm.username = ''
|
|
searchForm.status = undefined
|
|
handleSearch()
|
|
}
|
|
|
|
// 新增
|
|
function handleAdd() {
|
|
form.id = ''
|
|
form.username = ''
|
|
form.password = ''
|
|
form.name = ''
|
|
form.phone = ''
|
|
form.email = ''
|
|
form.position = ''
|
|
form.role = 'USER'
|
|
dialogVisible.value = true
|
|
}
|
|
|
|
// 编辑
|
|
function handleEdit(row: User) {
|
|
form.id = row.id
|
|
form.username = row.username
|
|
form.password = ''
|
|
form.name = row.name
|
|
form.phone = row.phone || ''
|
|
form.email = row.email || ''
|
|
form.position = row.position || ''
|
|
form.role = row.role
|
|
dialogVisible.value = true
|
|
}
|
|
|
|
// 提交
|
|
async function handleSubmit() {
|
|
const valid = await formRef.value?.validate()
|
|
if (!valid) return
|
|
|
|
submitLoading.value = true
|
|
try {
|
|
if (form.id) {
|
|
await updateUser(form.id, {
|
|
name: form.name,
|
|
phone: form.phone,
|
|
email: form.email,
|
|
position: form.position
|
|
})
|
|
ElMessage.success('更新成功')
|
|
} else {
|
|
await createUser({
|
|
username: form.username,
|
|
password: form.password,
|
|
name: form.name,
|
|
phone: form.phone,
|
|
email: form.email,
|
|
position: form.position,
|
|
role: form.role
|
|
})
|
|
ElMessage.success('创建成功')
|
|
}
|
|
dialogVisible.value = false
|
|
loadData()
|
|
} finally {
|
|
submitLoading.value = false
|
|
}
|
|
}
|
|
|
|
// 更新状态
|
|
async function handleStatus(row: User) {
|
|
const newStatus = row.status === 1 ? 0 : 1
|
|
await ElMessageBox.confirm(
|
|
`确定要${newStatus === 1 ? '启用' : '禁用'}该用户吗?`,
|
|
'提示',
|
|
{ type: 'warning' }
|
|
)
|
|
await updateUserStatus(row.id, newStatus)
|
|
ElMessage.success('操作成功')
|
|
loadData()
|
|
}
|
|
|
|
// 删除
|
|
async function handleDelete(row: User) {
|
|
await ElMessageBox.confirm('确定要删除该用户吗?', '提示', { type: 'warning' })
|
|
await deleteUser(row.id)
|
|
ElMessage.success('删除成功')
|
|
loadData()
|
|
}
|
|
|
|
// 初始化
|
|
loadData()
|
|
</script>
|
|
|
|
<style scoped>
|
|
.user-page {
|
|
height: 100%;
|
|
}
|
|
|
|
.search-form {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.toolbar {
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.pagination {
|
|
margin-top: 16px;
|
|
justify-content: flex-end;
|
|
}
|
|
</style>
|