You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
exam/DataTable/index.vue

297 lines
7.6 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<!-- 组件容器使用 app-container 类名 -->
<div class="app-container">
<!-- 筛选条件容器 -->
<div class="filter-container">
<!-- 插槽用于插入自定义筛选内容 -->
<slot name="filter-content" />
<!-- Element UI 行布局 -->
<el-row>
<!-- Element UI 列布局 -->
<el-col>
<!-- options.addRoute 存在时显示添加按钮 -->
<el-button v-if="options.addRoute" type="primary" icon="el-icon-plus" @click="handleAdd">添加</el-button>
</el-col>
</el-row>
</div>
<!-- 当 multiShow 为 true 且 options.multiActions 存在时显示批量操作容器 -->
<div v-show="multiShow && options.multiActions" class="filter-container">
<!-- Element UI 下拉选择框,用于选择批量操作 -->
<el-select v-model="multiNow" :placeholder="selectedLabel" class="filter-item" style="width: 130px" @change="handleOption">
<!-- -->
<el-option
v-for="item in options.multiActions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<!-- Element UI 表格显示数据列表 -->
<el-table
v-loading="listLoading"
:data="dataList.records"
:header-cell-style="{'background':'#f2f3f4', 'color':'#555', 'font-weight':'bold', 'line-height':'32px'}"
border
fit
highlight-current-row
@selection-change="handleSelection"
>
<!-- options.multi true 时显示多选列 -->
<el-table-column
v-if="options.multi"
align="center"
type="selection"
width="55"
/>
<!-- 插槽用于插入自定义表格列 -->
<slot name="data-columns" />
</el-table>
<!-- 分页组件当总数据量大于 0 时显示 -->
<pagination v-show="dataList.total>0" :total="dataList.total" :page.sync="listQuery.current" :limit.sync="listQuery.size" @pagination="getList" />
</div>
</template>
<script>
// 从公共 API 模块导入列表查询、删除数据和更改状态的方法
import { fetchList, deleteData, changeState } from '@/api/common'
// 导入分页组件
import Pagination from '@/components/Pagination'
export default {
// 组件名称
name: 'PagingTable',
// 注册子组件
components: { Pagination },
// 组件入参
props: {
options: {
type: Object,
default: () => {
return {
// 批量操作选项数组
multiActions: [],
// 列表请求的 API 地址
listUrl: '/exam/api',
// 删除数据请求的 API 地址
deleteUrl: '',
// 更改状态请求的 API 地址
stateUrl: '',
// 是否支持批量操作
multi: false
}
}
},
// 列表查询参数
listQuery: {
type: Object,
default: () => {
return {
// 当前页码
current: 1,
// 每页显示的数据量
size: 10,
// 其他查询参数
params: {},
// 时间戳,用于防止缓存
t: 0
}
}
}
},
data() {
return {
// 接口返回的数据列表
dataList: {
// 总数据量
total: 0
},
// 数据加载状态标识
listLoading: true,
// 选中的数据 ID 数组
selectedIds: [],
// 选中的数据对象数组
selectedObjs: [],
// 显示已选中的项数提示文本
selectedLabel: '',
// 是否显示批量操作区域
multiShow: false,
// 当前选中的批量操作标识
multiNow: ''
}
},
watch: {
// 检测查询参数变化,当变化时重新获取数据列表
listQuery: {
handler() {
this.getList()
},
deep: true
}
},
// 组件创建完成后调用获取数据列表的方法
created() {
this.getList()
},
methods: {
/**
* 添加数据跳转方法
* 如果 options.addRoute 存在,则跳转到指定路由;否则打印提示信息
*/
handleAdd() {
if (this.options.addRoute) {
this.$router.push({ name: this.options.addRoute, params: {}})
return
}
console.log('未设置添加数据跳转路由!')
},
/**
* 查询数据列表方法
* 发送请求获取数据列表,并更新组件数据
*/
getList() {
this.listLoading = true
this.listQuery.t = new Date().getTime()
fetchList(this.options.listUrl, this.listQuery).then(response => {
this.dataList = response.data
this.listLoading = false
})
},
/**
* 搜索方法
* 重新调用获取数据列表的方法
*/
handleFilter() {
// 重新搜索
this.getList()
},
/**
* 批量操作回调方法
* 根据选中的批量操作标识执行相应操作
* @param {string} v - 当前选中的批量操作标识
*/
handleOption(v) {
this.multiNow = ''
// 内部消化的操作
if (v === 'delete') {
this.handleDelete()
return
}
if (v === 'enable') {
this.handleState(0)
return
}
if (v === 'disable') {
this.handleState(1)
return
}
// 向外回调的操作
this.$emit('multi-actions', { opt: v, ids: this.selectedIds })
},
/**
* 修改状态方法,用于启用或禁用数据
* 发送请求修改选中数据的状态,并在成功后重新获取数据列表
* @param {number} state - 要修改成的状态值
*/
handleState(state) {
// 修改状态
changeState(this.options.stateUrl, this.selectedIds, state).then(response => {
if (response.code === 0) {
this.$message({
type: 'success',
message: '状态修改成功!'
})
// 重新搜索
this.getList()
}
})
},
/**
* 删除数据方法
* 先检查是否有选中数据,有则弹出确认对话框,确认后发送删除请求并重新获取数据列表
*/
handleDelete() {
if (this.selectedIds.length === 0) {
this.$message({
message: '请至少选择一条数据!',
type: 'warning'
})
return
}
// 删除
this.$confirm('确实要删除吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteData(this.options.deleteUrl, this.selectedIds).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
})
this.getList()
})
})
},
/**
* 列表多选操作方法
* 处理表格多选变化事件,更新选中数据的相关信息并触发事件
* @param {Array} val - 当前选中的数据对象数组
*/
handleSelection(val) {
const ids = []
val.forEach(row => {
ids.push(row.id)
})
this.selectedObjs = val
this.selectedIds = ids
this.multiShow = ids.length > 0
this.selectedLabel = '已选' + ids.length + '项'
this.$emit('select-changed', { ids: this.selectedIds, objs: this.selectedObjs })
}
}
}
</script>
<style>
/* 筛选容器内筛选项的样式,设置左外边距 */
.filter-container .filter-item{
margin-left: 5px;
}
/* 筛选容器内第一个筛选项的样式,取消左外边距 */
.filter-container .filter-item:first-child{
margin-left: 0px;
}
</style>