优化更新

This commit is contained in:
2026-01-23 22:05:09 +08:00
parent 8283555457
commit 0608f0febb
14 changed files with 667 additions and 622 deletions
+36 -115
View File
@@ -22,14 +22,14 @@
<a-button type="primary" @click="handleAdd">
<template #icon><plus-outlined /></template>
</a-button>
<a-button danger :disabled="selection.length === 0" @click="handleBatchDelete">
<a-button danger :disabled="selectedRows.length === 0" @click="handleBatchDelete">
<template #icon><delete-outlined /></template>
</a-button>
</div>
</div>
<div class="table-content">
<scTable ref="tableRef" :columns="columns" :data-source="tableData" :loading="loading" :pagination="false"
:row-key="rowKey" :row-selection="rowSelection" @refresh="loadData" @select="handleSelectChange"
:row-key="rowKey" :row-selection="rowSelection" @refresh="refreshTable" @select="handleSelectChange"
@selectAll="handleSelectAll">
<template #action="{ record }">
<a-space>
@@ -49,18 +49,40 @@
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import scTable from '@/components/scTable/index.vue'
import saveDialog from './save.vue'
import authApi from '@/api/auth'
import { useTable } from '@/hooks/useTable'
defineOptions({
name: 'authDepartment'
})
// 表格引用
const tableRef = ref(null)
// 使用useTable hooks
const {
tableRef,
searchForm,
tableData,
loading,
selectedRows,
rowSelection,
handleSearch,
handleReset,
handleSelectChange,
handleSelectAll,
refreshTable
} = useTable({
api: authApi.department.list.get,
searchForm: {
keyword: ''
},
columns: [],
needPagination: false,
needSelection: true,
immediateLoad: false
})
// 对话框状态
const dialog = reactive({
@@ -70,29 +92,9 @@ const dialog = reactive({
// 弹窗引用
const saveDialogRef = ref(null)
// 选中的行
const selection = ref([])
// 搜索表单
const searchForm = reactive({
keyword: ''
})
// 表格数据
const tableData = ref([])
const loading = ref(false)
// 行key
const rowKey = 'id'
// 行选择配置
const rowSelection = computed(() => ({
selectedRowKeys: selection.value.map(item => item.id),
onChange: (selectedRowKeys, selectedRows) => {
selection.value = selectedRows
}
}))
// 表格列配置
const columns = [
{ title: '#', dataIndex: '_index', key: '_index', width: 60, align: 'center' },
@@ -102,69 +104,6 @@ const columns = [
{ title: '操作', dataIndex: 'action', key: 'action', width: 220, align: 'center', slot: 'action', fixed: 'right' }
]
// 加载部门列表数据
const loadData = async () => {
loading.value = true
try {
const params = {
is_tree: 1,
...searchForm
}
const res = await authApi.department.list.get(params)
if (res.code === 1) {
tableData.value = res.data || []
} else {
message.error(res.message || '加载数据失败')
}
} catch (error) {
console.error('加载部门列表失败:', error)
message.error('加载数据失败')
} finally {
loading.value = false
}
}
// 选择变化处理
const handleSelectChange = (record, selected, selectedRows) => {
if (selected) {
selection.value.push(record)
} else {
const index = selection.value.findIndex(item => item.id === record.id)
if (index > -1) {
selection.value.splice(index, 1)
}
}
}
// 全选/取消全选处理
const handleSelectAll = (selected, selectedRows, changeRows) => {
if (selected) {
changeRows.forEach(record => {
if (!selection.value.find(item => item.id === record.id)) {
selection.value.push(record)
}
})
} else {
changeRows.forEach(record => {
const index = selection.value.findIndex(item => item.id === record.id)
if (index > -1) {
selection.value.splice(index, 1)
}
})
}
}
// 搜索
const handleSearch = () => {
loadData()
}
// 重置
const handleReset = () => {
searchForm.keyword = ''
selection.value = []
loadData()
}
// 新增部门
const handleAdd = () => {
@@ -196,7 +135,7 @@ const handleDelete = async (record) => {
const res = await authApi.department.delete.post({ id: record.id })
if (res.code === 1) {
message.success('删除成功')
loadData()
refreshTable()
} else {
message.error(res.message || '删除失败')
}
@@ -208,25 +147,25 @@ const handleDelete = async (record) => {
// 批量删除
const handleBatchDelete = () => {
if (selection.value.length === 0) {
if (selectedRows.value.length === 0) {
message.warning('请选择要删除的部门')
return
}
Modal.confirm({
title: '确认删除',
content: `确定删除选中的 ${selection.value.length} 个部门吗?如果删除项中含有子集将会被一并删除`,
content: `确定删除选中的 ${selectedRows.value.length} 个部门吗?如果删除项中含有子集将会被一并删除`,
okText: '确定',
cancelText: '取消',
okType: 'danger',
onOk: async () => {
try {
const ids = selection.value.map(item => item.id)
const ids = selectedRows.value.map(item => item.id)
const res = await authApi.department.delete.post({ ids })
if (res.code === 1) {
message.success('删除成功')
selection.value = []
loadData()
selectedRows.value = []
refreshTable()
} else {
message.error(res.message || '删除失败')
}
@@ -238,32 +177,14 @@ const handleBatchDelete = () => {
})
}
// 根据ID获取树节点
const filterTree = (id) => {
let target = null
function filter(tree) {
for (const item of tree) {
if (item.id === id) {
target = item
return
}
if (item.children) {
filter(item.children)
}
}
}
filter(tableData.value)
return target
}
// 保存成功回调
const handleSaveSuccess = (data, mode) => {
loadData()
const handleSaveSuccess = () => {
refreshTable()
}
// 初始化
onMounted(() => {
loadData()
refreshTable()
})
</script>
+40 -130
View File
@@ -23,17 +23,17 @@
<a-button type="primary" @click="handleAdd">
<template #icon><plus-outlined /></template>
</a-button>
<a-button danger :disabled="selection.length === 0" @click="handleBatchDelete">
<a-button danger :disabled="selectedRows.length === 0" @click="handleBatchDelete">
<template #icon><delete-outlined /></template>
</a-button>
<a-button :disabled="selection.length !== 1" @click="handlePermission">
<a-button :disabled="selectedRows.length !== 1" @click="handlePermission">
<template #icon><key-outlined /></template>
</a-button>
</div>
</div>
<div class="table-content">
<scTable ref="tableRef" :columns="columns" :data-source="tableData" :loading="loading"
:pagination="pagination" :row-key="rowKey" :row-selection="rowSelection" @refresh="loadData"
:pagination="pagination" :row-key="rowKey" :row-selection="rowSelection" @refresh="refreshTable"
@paginationChange="handlePaginationChange" @select="handleSelectChange" @selectAll="handleSelectAll">
<template #status="{ record }">
<a-tag :color="record.status === 1 ? 'success' : 'error'">
@@ -62,19 +62,42 @@
</template>
<script setup>
import { ref, reactive, onMounted, computed } from 'vue'
import { ref, reactive } from 'vue'
import { message, Modal } from 'ant-design-vue'
import scTable from '@/components/scTable/index.vue'
import saveDialog from './save.vue'
import permissionDialog from './permission.vue'
import authApi from '@/api/auth'
import { useTable } from '@/hooks/useTable'
defineOptions({
name: 'authRole'
})
// 表格引用
const tableRef = ref(null)
// 使用useTable hooks
const {
tableRef,
searchForm,
tableData,
loading,
pagination,
selectedRows,
rowSelection,
handleSearch,
handleReset,
handlePaginationChange,
handleSelectChange,
handleSelectAll,
refreshTable
} = useTable({
api: authApi.role.list.get,
searchForm: {
keyword: ''
},
columns: [],
needPagination: true,
needSelection: true
})
// 对话框状态
const dialog = reactive({
@@ -86,39 +109,9 @@ const dialog = reactive({
const saveDialogRef = ref(null)
const permissionDialogRef = ref(null)
// 选中的行
const selection = ref([])
// 搜索表单
const searchForm = reactive({
keyword: ''
})
// 表格数据
const tableData = ref([])
const loading = ref(false)
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0,
showSizeChanger: true,
showTotal: (total) => `${total}`,
pageSizeOptions: ['20', '50', '100', '200']
})
// 行key
const rowKey = 'id'
// 行选择配置
const rowSelection = computed(() => ({
selectedRowKeys: selection.value.map(item => item.id),
onChange: (selectedRowKeys, selectedRows) => {
selection.value = selectedRows
}
}))
// 表格列配置
const columns = [
{ title: 'ID', dataIndex: 'id', key: 'id', width: 80, align: 'center' },
@@ -129,80 +122,6 @@ const columns = [
{ title: '操作', dataIndex: 'action', key: 'action', width: 200, align: 'center', slot: 'action', fixed: 'right' }
]
// 分页变化处理
const handlePaginationChange = ({ page, pageSize }) => {
pagination.current = page
pagination.pageSize = pageSize
loadData()
}
// 加载角色列表数据
const loadData = async () => {
loading.value = true
try {
const params = {
page: pagination.current,
limit: pagination.pageSize,
...searchForm
}
const res = await authApi.role.list.get(params)
if (res.code === 1) {
tableData.value = res.data?.data || []
pagination.total = res.data?.total || 0
} else {
message.error(res.message || '加载数据失败')
}
} catch (error) {
console.error('加载角色列表失败:', error)
message.error('加载数据失败')
} finally {
loading.value = false
}
}
// 选择变化处理
const handleSelectChange = (record, selected, selectedRows) => {
if (selected) {
selection.value.push(record)
} else {
const index = selection.value.findIndex(item => item.id === record.id)
if (index > -1) {
selection.value.splice(index, 1)
}
}
}
// 全选/取消全选处理
const handleSelectAll = (selected, selectedRows, changeRows) => {
if (selected) {
changeRows.forEach(record => {
if (!selection.value.find(item => item.id === record.id)) {
selection.value.push(record)
}
})
} else {
changeRows.forEach(record => {
const index = selection.value.findIndex(item => item.id === record.id)
if (index > -1) {
selection.value.splice(index, 1)
}
})
}
}
// 搜索
const handleSearch = () => {
pagination.current = 1
loadData()
}
// 重置
const handleReset = () => {
searchForm.keyword = ''
selection.value = []
pagination.current = 1
loadData()
}
// 新增角色
const handleAdd = () => {
@@ -234,7 +153,7 @@ const handleDelete = async (record) => {
const res = await authApi.role.delete.post({ id: record.id })
if (res.code === 1) {
message.success('删除成功')
loadData()
refreshTable()
} else {
message.error(res.message || '删除失败')
}
@@ -246,25 +165,25 @@ const handleDelete = async (record) => {
// 批量删除
const handleBatchDelete = () => {
if (selection.value.length === 0) {
if (selectedRows.value.length === 0) {
message.warning('请选择要删除的角色')
return
}
Modal.confirm({
title: '确认删除',
content: `确定删除选中的 ${selection.value.length} 个角色吗?`,
content: `确定删除选中的 ${selectedRows.value.length} 个角色吗?`,
okText: '确定',
cancelText: '取消',
okType: 'danger',
onOk: async () => {
try {
const ids = selection.value.map(item => item.id)
const ids = selectedRows.value.map(item => item.id)
const res = await authApi.role.delete.post({ ids })
if (res.code === 1) {
message.success('删除成功')
selection.value = []
loadData()
selectedRows.value = []
refreshTable()
} else {
message.error(res.message || '删除失败')
}
@@ -278,34 +197,25 @@ const handleBatchDelete = () => {
// 权限设置
const handlePermission = () => {
if (selection.value.length !== 1) {
if (selectedRows.value.length !== 1) {
message.error('请选择一个角色进行权限设置')
return
}
dialog.permission = true
setTimeout(() => {
permissionDialogRef.value?.open().setData(selection.value[0])
permissionDialogRef.value?.open().setData(selectedRows.value[0])
}, 0)
}
// 保存成功回调
const handleSaveSuccess = (data, mode) => {
if (mode === 'add') {
loadData()
} else if (mode === 'edit') {
loadData()
}
const handleSaveSuccess = () => {
refreshTable()
}
// 权限设置成功回调
const permissionSuccess = () => {
loadData()
refreshTable()
}
// 初始化
onMounted(() => {
loadData()
})
</script>
<style scoped lang="scss">
+42 -98
View File
@@ -35,9 +35,9 @@
<a-button type="primary" @click="handleSearch">
<template #icon><search-outlined /></template>
</a-button>
<a-button @click="handleReset">
<template #icon><redo-outlined /></template>
</a-button>
<a-button @click="handleUserReset">
<template #icon><redo-outlined /></template>
</a-button>
</a-space>
</a-form-item>
</a-form>
@@ -52,9 +52,9 @@
</div>
</div>
<div class="table-content">
<scTable ref="tableRef" :columns="columns" :data-source="tableData" :loading="loading"
:pagination="pagination" :row-key="rowKey" @refresh="loadData"
@paginationChange="handlePaginationChange">
<scTable ref="tableRef" :columns="columns" :data-source="tableData" :loading="loading"
:pagination="pagination" :row-key="rowKey" @refresh="refreshTable"
@paginationChange="handlePaginationChange">
<template #avatar="{ record }">
<a-avatar :src="record.avatar" :size="32">
<template #icon><user-outlined /></template>
@@ -102,13 +102,33 @@ import scTable from '@/components/scTable/index.vue'
import saveDialog from './save.vue'
import roleDialog from './role.vue'
import authApi from '@/api/auth'
import { useTable } from '@/hooks/useTable'
defineOptions({
name: 'authUser'
})
// 表格引用
const tableRef = ref(null)
// 使用useTable hooks
const {
tableRef,
searchForm,
tableData,
loading,
pagination,
handleSearch,
handleReset,
handlePaginationChange,
refreshTable
} = useTable({
api: authApi.users.list.get,
searchForm: {
username: '',
nickname: '',
department_id: null
},
columns: [],
needPagination: true
})
// 对话框状态
const dialog = reactive({
@@ -126,37 +146,9 @@ const filteredDepartmentTree = ref([])
const selectedDeptKeys = ref([])
const departmentKeyword = ref('')
// 搜索表单
const searchForm = reactive({
username: '',
nickname: '',
department_id: null
})
// 表格数据
const tableData = ref([])
const loading = ref(false)
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0,
showSizeChanger: true,
showTotal: (total) => `${total}`,
pageSizeOptions: ['20', '50', '100', '200']
})
// 行key
const rowKey = 'id'
// 分页变化处理
const handlePaginationChange = ({ page, pageSize }) => {
pagination.current = page
pagination.pageSize = pageSize
loadData()
}
// 表格列配置
const columns = [
{ title: '头像', dataIndex: 'avatar', key: 'avatar', width: 80, align: 'center', slot: 'avatar' },
@@ -210,34 +202,15 @@ const handleDeptSearch = (e) => {
filteredDepartmentTree.value = filterTree(departmentTree.value)
}
// 加载用户列表数据
const loadData = async () => {
loading.value = true
try {
const params = {
page: pagination.current,
limit: pagination.pageSize,
...searchForm
}
const res = await authApi.users.list.get(params)
if (res.code === 1) {
tableData.value = res.data?.data || []
pagination.total = res.data?.total || 0
} else {
message.error(res.message || '加载数据失败')
}
} catch (error) {
console.error('加载用户列表失败:', error)
message.error('加载数据失败')
} finally {
loading.value = false
}
}
// 表格变化处理(排序、筛选)
const handleTableChange = (pagination, filters, sorter) => {
// 如果需要处理排序或筛选,可以在这里添加逻辑
console.log('表格变化:', { pagination, filters, sorter })
// 重置 - 覆盖useTable的handleReset以添加额外逻辑
const handleUserReset = () => {
searchForm.username = ''
searchForm.nickname = ''
searchForm.department_id = null
selectedDeptKeys.value = []
departmentKeyword.value = ''
filteredDepartmentTree.value = departmentTree.value
handleReset()
}
// 部门选择事件
@@ -247,31 +220,7 @@ const onDeptSelect = (selectedKeys) => {
} else {
searchForm.department_id = null
}
pagination.current = 1
loadData()
}
// 搜索
const handleSearch = () => {
pagination.current = 1
loadData()
}
// 重置
const handleReset = () => {
searchForm.username = ''
searchForm.nickname = ''
searchForm.department_id = null
selectedDeptKeys.value = []
departmentKeyword.value = ''
filteredDepartmentTree.value = departmentTree.value
pagination.current = 1
loadData()
}
// 刷新表格
const refreshTable = () => {
loadData()
handleSearch()
}
// 导出数据
@@ -320,7 +269,7 @@ const handleDelete = async (record) => {
const res = await authApi.users.delete.post({ id: record.id })
if (res.code === 1) {
message.success('删除成功')
loadData()
refreshTable()
} else {
message.error(res.message || '删除失败')
}
@@ -331,23 +280,18 @@ const handleDelete = async (record) => {
}
// 保存成功回调
const handleSaveSuccess = (data, mode) => {
if (mode === 'add') {
loadData()
} else if (mode === 'edit') {
loadData()
}
const handleSaveSuccess = () => {
refreshTable()
}
// 角色设置成功回调
const handleRoleSuccess = () => {
loadData()
refreshTable()
}
// 初始化
onMounted(() => {
loadDepartmentTree()
loadData()
})
</script>
+35 -93
View File
@@ -28,7 +28,7 @@
<a-button type="primary" @click="handleSearch">
<template #icon><search-outlined /></template>
</a-button>
<a-button @click="handleReset">
<a-button @click="handleLogReset">
<template #icon><redo-outlined /></template>
</a-button>
</a-space>
@@ -44,7 +44,7 @@
</div>
<div class="table-content">
<scTable ref="tableRef" :columns="columns" :data-source="tableData" :loading="loading"
:pagination="pagination" :row-key="rowKey" @refresh="loadData" @paginationChange="handlePaginationChange"
:pagination="pagination" :row-key="rowKey" @refresh="refreshTable" @paginationChange="handlePaginationChange"
:row-selection="rowSelection">
<template #method="{ record }">
<a-tag :color="getMethodColor(record.method)">{{ record.method }}</a-tag>
@@ -67,19 +67,44 @@
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ref, reactive, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { SearchOutlined, RedoOutlined, DeleteOutlined, FolderOutlined, FileOutlined } from '@ant-design/icons-vue'
import scTable from '@/components/scTable/index.vue'
import logInfoDialog from './info.vue'
import systemApi from '@/api/system'
import { useTable } from '@/hooks/useTable'
defineOptions({
name: 'systemLog'
})
// 表格引用
const tableRef = ref(null)
// 使用useTable hooks
const {
tableRef,
searchForm,
tableData,
loading,
pagination,
selectedRowKeys,
rowSelection,
handleSearch,
handleReset,
handlePaginationChange,
refreshTable
} = useTable({
api: systemApi.log.list.get,
searchForm: {
title: '',
method: null,
status: null,
created_at: []
},
columns: [],
needPagination: true,
needSelection: true,
immediateLoad: false
})
// 对话框状态
const dialog = reactive({
@@ -89,6 +114,7 @@ const dialog = reactive({
// 弹窗引用
const infoDialogRef = ref(null)
// 树数据
const treeData = ref([
{
@@ -116,39 +142,6 @@ const treeData = ref([
// 选中的树节点
const selectedKeys = ref([])
// 选中的行
const selectedRowKeys = ref([])
// 行选择配置
const rowSelection = computed(() => ({
selectedRowKeys: selectedRowKeys.value,
onChange: (selectedKeys) => {
selectedRowKeys.value = selectedKeys
},
}))
// 搜索表单
const searchForm = reactive({
title: '',
method: null,
status: null,
created_at: []
})
// 表格数据
const tableData = ref([])
const loading = ref(false)
// 分页配置
const pagination = reactive({
current: 1,
pageSize: 20,
total: 0,
showSizeChanger: true,
showTotal: (total) => `${total}`,
pageSizeOptions: ['20', '50', '100', '200']
})
// 行key
const rowKey = 'id'
@@ -175,40 +168,6 @@ const columns = [
{ title: '操作', dataIndex: 'action', key: 'action', width: 150, align: 'center', slot: 'action', fixed: 'right' }
]
// 加载日志列表数据
const loadData = async () => {
loading.value = true
try {
const params = {
page: pagination.current,
limit: pagination.pageSize,
title: searchForm.title,
method: searchForm.method,
status: searchForm.status,
created_at: searchForm.created_at
}
const res = await systemApi.log.list.get(params)
if (res.code === 1) {
tableData.value = res.data?.data || []
pagination.total = res.data?.total || 0
} else {
message.error(res.message || '加载数据失败')
}
} catch (error) {
console.error('加载日志列表失败:', error)
message.error('加载数据失败')
} finally {
loading.value = false
}
}
// 分页变化处理
const handlePaginationChange = ({ page, pageSize }) => {
pagination.current = page
pagination.pageSize = pageSize
loadData()
}
// 树节点选择事件
const onSelect = (selectedKeys, info) => {
@@ -230,27 +189,10 @@ const onSelect = (selectedKeys, info) => {
searchForm.status = null
}
pagination.current = 1
loadData()
refreshTable()
}
}
// 搜索
const handleSearch = () => {
pagination.current = 1
loadData()
}
// 重置
const handleReset = () => {
searchForm.title = ''
searchForm.method = null
searchForm.status = null
searchForm.timeRange = []
selectedKeys.value = []
pagination.current = 1
loadData()
}
// 查看日志详情
const handleView = (record) => {
dialog.info = true
@@ -265,7 +207,7 @@ const handleDelete = async (record) => {
const res = await systemApi.log.delete.post({ id: record.id })
if (res.code === 1) {
message.success('删除成功')
loadData()
refreshTable()
selectedRowKeys.value = []
} else {
message.error(res.message || '删除失败')
@@ -295,7 +237,7 @@ const handleClearLog = () => {
await Promise.all(promises)
message.success('清空成功')
selectedRowKeys.value = []
loadData()
refreshTable()
} catch (error) {
console.error('清空日志失败:', error)
message.error('清空失败')
@@ -306,7 +248,7 @@ const handleClearLog = () => {
// 初始化
onMounted(() => {
loadData()
refreshTable()
})
</script>