Introducing new features. 优化表单名称列表页查询,增加表格hooks

This commit is contained in:
aeizzz 2023-02-01 15:16:03 +08:00
parent 90572de7ca
commit 1a898145b2
5 changed files with 326 additions and 128 deletions

View File

@ -0,0 +1,56 @@
<template>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
class="mt15"
:pager-count="5"
:page-sizes="prop.pageSizes"
v-model:current-page="prop.current"
background
v-model:page-size="prop.size"
:layout="prop.layout"
:total="prop.total"
>
</el-pagination>
</template>
<script setup lang="ts" name="pagination">
const emit = defineEmits(['sizeChange', 'currentChange'])
const prop = defineProps({
current: {
type: Number,
default: 1,
},
size: {
type: Number,
default: 10,
},
total: {
type: Number,
default: 0,
},
pageSizes: {
type: Array,
default: [1, 10, 20, 50, 100, 200],
},
layout: {
type: String,
default: "total, sizes, prev, pager, next, jumper",
}
})
//
const sizeChangeHandle = (val: number) => {
emit('sizeChange',val)
};
//
const currentChangeHandle = (val: number) => {
emit('currentChange',val)
};
</script>
<style scoped>
</style>

View File

@ -0,0 +1,87 @@
<template>
<div class="head-container">
<el-input
v-model="searchName"
:placeholder="placeholder"
clearable
style="margin-bottom: 20px"
@change="getDeptTree"
/>
<el-tree
:data="state.List"
:props="props"
:expand-on-click-node="false"
ref="deptTreeRef"
:loading="state.localLoading"
node-key="id"
highlight-current
default-expand-all
@node-click="handleNodeClick"
/>
</div>
</template>
<script setup lang="ts" name="query-tree">
import {onMounted, reactive, ref, unref} from "vue";
const emit = defineEmits(['search', 'nodeClick'])
const {placeholder, props, query, loading, searchKey} = defineProps({
props: {
type: Object,
default: () => {
return {
label: 'name',
children: 'children',
value: 'id'
}
}
},
placeholder: {
type: String,
default: ''
},
loading: {
type: Boolean,
default: false
},
query: {
type: Function,
required: true
}
})
const state = reactive({
List: [],
localLoading: loading
})
const searchName = ref()
const handleNodeClick = (item: any) => {
emit('nodeClick',item)
}
const getDeptTree = () => {
console.log('3333')
if(query instanceof Function){
state.localLoading = true
const result = query(unref(searchName))
if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') {
result.then((r: any) => {
state.List = r.data
})
}
}
}
onMounted(() => {
getDeptTree()
})
</script>
<style scoped>
</style>

140
src/hooks/table.ts Normal file
View File

@ -0,0 +1,140 @@
import {onMounted} from "vue";
import {ElMessage} from "element-plus";
export interface BasicTableProps{
// 是否在创建页面时,调用数据列表接口
createdIsNeed?: boolean
// 是否需要分页
isPage?: boolean
// 查询条件
queryForm?: any
// 数据列表
dataList?: any[]
// 分页属性
pagination?: Pagination,
// 数据列表loading状态
dataListLoading?: boolean
// 数据列表,多选项
dataListSelections?: any[]
// 接口api
pageList?: (...arg: any) => Promise<any>
// loading
loading?: Boolean
}
export interface Pagination{
// 排序字段
order?: string
// 是否升序
asc?: boolean
// 当前页码
current?: number
// 每页数
size?: number
// 总条数
total?: number
pageSizes?: any[]
layout?: String
}
export function useTable(options?: BasicTableProps) {
const defaultOptions: BasicTableProps = {
dataListLoading: false,
createdIsNeed: true,
isPage: true,
queryForm: {},
dataList: [],
pagination: {
order: '',
asc: false,
current: 1,
size: 10,
total: 0,
pageSizes: [1, 10, 20, 50, 100, 200],
layout: "total, sizes, prev, pager, next, jumper"
} as Pagination,
dataListSelections: [],
loading: false
}
const mergeDefaultOptions = (options: any, props: any): BasicTableProps => {
for (const key in options) {
if (!Object.getOwnPropertyDescriptor(props, key)) {
props[key] = options[key]
}
}
return props
}
// 覆盖默认值
const state = mergeDefaultOptions(defaultOptions, options)
const query =() => {
if (state.pageList) {
state.loading = true
state.pageList({
...state.queryForm,
current: state.pagination?.current,
size: state.pagination?.size,
order: state.pagination?.order,
asc: state.pagination?.asc,
}).then(res => {
state.dataList = state.isPage ? res.data.records : res.data
state.pagination!.total = state.isPage ? res.data.total : 0
}).catch(err => {
ElMessage.error(err.msg)
}).finally(() => {
state.loading = false;
})
}
}
onMounted(() => {
if (state.createdIsNeed) {
query()
}
})
// 分页改变
const sizeChangeHandle = (val: number) => {
state.pagination!.size = val;
query();
};
// 分页改变
const currentChangeHandle = (val: number) => {
state.pagination!.current = val;
query();
};
// 排序
const sortChangeHandle = (data: any) => {
const { prop, order } = data
if (prop && order) {
state.pagination!.order = prop
state.pagination!.asc = order === 'ascending'
} else {
state.pagination!.order = ''
}
query()
}
const getDataList = () => {
state.pagination!.current = 1
query()
}
return {
getDataList,
sizeChangeHandle,
currentChangeHandle,
sortChangeHandle,
}
}

View File

@ -3,49 +3,31 @@
<el-row :gutter="20">
<el-col :span="4" :xs="24">
<el-card shadow="hover" class="layout-padding-auto">
<div class="head-container">
<el-input
v-model="deptData.search.deptName"
placeholder="请输入部门名称"
clearable
prefix-icon="Search"
style="margin-bottom: 20px"
@change="getDeptTree"
/>
</div>
<div class="head-container">
<el-tree
:data="deptData.deptList"
:props="{ label: 'name', children: 'children',value: 'id' }"
:expand-on-click-node="false"
ref="deptTreeRef"
:loading="deptData.loading"
node-key="id"
highlight-current
default-expand-all
@node-click="handleNodeClick"
/>
</div>
<query-tree
@node-click="handleNodeClick"
:placeholder="deptData.placeholder"
:query="deptData.queryList"
/>
</el-card>
</el-col>
<el-col :span="20" :xs="24">
<el-card shadow="hover" class="layout-padding-auto">
<div class="system-user-search mb15">
<el-input size="default" placeholder="请输入用户名称" style="max-width: 180px" v-model="state.search.username"> </el-input>
<el-button size="default" type="primary" class="ml10" @click="getTableData">
<el-input size="default" placeholder="请输入用户名称" style="max-width: 180px" v-model="state.queryForm.username"> </el-input>
<el-button size="default" type="primary" class="ml10" @click="getDataList">
<el-icon>
<ele-Search />
</el-icon>
查询
</el-button>
<el-button size="default" type="success" class="ml10" @click="onOpenAddUser('add')">
<el-button size="default" type="success" class="ml10" @click="userDialogRef.openDialog('add')">
<el-icon>
<ele-FolderAdd />
</el-icon>
新增用户
</el-button>
</div>
<el-table :data="state.tableData.data" v-loading="state.tableData.loading" style="width: 100%">
<el-table :data="state.dataList" v-loading="state.loading" style="width: 100%">
<el-table-column type="index" label="序号" width="60" />
<el-table-column prop="username" label="用户名" show-overflow-tooltip></el-table-column>
<el-table-column prop="name" label="姓名" show-overflow-tooltip></el-table-column>
@ -69,31 +51,25 @@
<el-table-column prop="createTime" label="创建时间" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="100">
<template #default="scope">
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onOpenEditUser('edit', scope.row)"
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="userDialogRef.openDialog('edit', scope.row)"
>修改</el-button
>
<el-button :disabled="scope.row.userName === 'admin'" size="small" text type="primary" @click="onRowDel(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="onHandleSizeChange"
@current-change="onHandleCurrentChange"
class="mt15"
:pager-count="5"
:page-sizes="[10, 20, 30]"
v-model:current-page="state.tableData.param.pageNum"
background
v-model:page-size="state.tableData.param.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="state.tableData.total"
<pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
v-bind="state.pagination"
>
</el-pagination>
</pagination>
</el-card>
</el-col>
</el-row>
<UserDialog ref="userDialogRef" @refresh="getTableData()" />
<UserDialog ref="userDialogRef" @refresh="getDataList()" />
</div>
</template>
@ -102,81 +78,49 @@ import { defineAsyncComponent, reactive, onMounted, ref } from 'vue';
import { ElMessageBox, ElMessage } from 'element-plus';
import { pageList, delObj } from '/@/api/admin/user'
import { depttree } from '/@/api/admin/dept'
import {BasicTableProps, useTable} from '/@/hooks/table'
//
const UserDialog = defineAsyncComponent(() => import('/@/views/system/user/dialog.vue'));
const UserDialog = defineAsyncComponent(() => import('./form.vue'));
const pagination = defineAsyncComponent(() => import('/@/components/Pagination/index.vue'))
const QueryTree = defineAsyncComponent(() => import('/@/components/QueryTree/index.vue'))
//
const userDialogRef = ref();
const state = reactive({
tableData: {
data: [],
total: 0,
loading: false,
param: {
pageNum: 1,
pageSize: 10,
},
},
search: {
// API
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {
deptId: '',
username: ''
}
},
pageList: pageList // H
});
const search = reactive({
deptName: ''
})
// 使
const deptData = reactive({
deptList: [],
search: {
deptName: ''
queryList: (name:String) => {
return depttree({
deptName: name
})
},
loading: false
placeholder: '输入部门名称'
})
//
const getTableData = () => {
state.tableData.loading = true;
pageList(state.search).then(res => {
state.tableData.data = res.data.records;
state.tableData.total = res.data.total;
state.tableData.loading = false;
}).catch(err => {
ElMessage.error(err.msg)
state.tableData.loading = false;
})
};
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle
} = useTable(state)
//
const getDeptTree = () => {
deptData.loading = true
depttree(deptData.search).then(res => {
deptData.deptList = res.data
}).catch(err => {
ElMessage.error(err.msg)
}).finally(() => {
deptData.loading = false
})
}
//
//
const handleNodeClick = (e: any) => {
state.search.deptId = e.id
getTableData()
state.queryForm.deptId = e.id
getDataList()
}
//
const onOpenAddUser = (type: string) => {
userDialogRef.value.openDialog(type);
};
//
const onOpenEditUser = (type: string, row: any) => {
userDialogRef.value.openDialog(type, row);
};
//
const onRowDel = (row: any) => {
ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.username}”,是否继续?`, '提示', {
@ -187,40 +131,11 @@ const onRowDel = (row: any) => {
.then(() => {
//
delObj(row.userId).then(res => {
getTableData();
getDataList();
ElMessage.success('删除成功');
}).catch(err => {
ElMessage.error(err.msg)
})
})
};
//
const onHandleSizeChange = (val: number) => {
state.tableData.param.pageSize = val;
getTableData();
};
//
const onHandleCurrentChange = (val: number) => {
state.tableData.param.pageNum = val;
getTableData();
};
//
onMounted(() => {
getTableData();
getDeptTree();
});
</script>
<style scoped lang="scss">
.system-user-container {
:deep(.el-card__body) {
display: flex;
flex-direction: column;
flex: 1;
overflow: auto;
.el-table {
flex: 1;
}
}
}
</style>