<template>
<div>
<Searchbar :searchBarConf='searchBarConf'/>
<Table :tableConf='tableConf'>
<div slot="btns" slot-scope="slotProps" v-bind="slotProps.itemProps">
<el-button type='text' @click="onEditor(slotProps)" > 编辑 </el-button>
</div>
</Table>
<Pagination />
</div>
</template>
<script>
import { reactive, computed, toRefs, provide } from '@vue/composition-api'
import {
tableConf,
searchBarConf,
confHook
} from './model'
import { delPop, reqSuccessTip, reqFailTip, asyncVessel } from '@/utils/tool'
import * as api from './api'
import {
tableHook,
injectMark,
Pagination,
Searchbar,
Table
} from '@/components/manage-table/index.js'
const tableConf = {
props: {
},
columns: [
{ label: '用户id', prop: 'id', align: 'center', sortable: true },
{ label: '用户昵称', prop: 'realName', align: 'center' },
{ label: '参团数', prop: 'joinGroupNum', align: 'center', sortable: true },
{ label: '订货数', prop: 'buyProductNum', align: 'center', sortable: true },
{ label: '操作', prop: 'btns', align: 'center', width: 80, slot: 'btns' }
]
}
const searchBarConf = [
{
col: 6,
cmp: 'el-input',
cmpProps:{
size:'small',
placeholder: '请输入完整的手机号码'
},
formItemProp: {
label: '手机号码',
prop: 'phone'
},
},
]
export default {
components:{
Pagination,
Searchbar,
Table
},
setup(){
// 创建state
const tableState = tableHook( api.tableList )
// 注入组件依赖
provide(injectMark, tableState)
// 表格更新
const updateTable = tableState.onSearchNoQuery
const onEditor = (row) => {
console.log(row);
updateTable()
}
return {
tableConf,
searchBarConf,
}
}
}
</script>
/**
* author: huhaiguo
* date: 2019-51-26 10:12
* summary: 表格功能逻辑
*/
import { reactive, computed, toRefs, ref, watch } from '@vue/composition-api'
import cloneDeep from 'lodash/cloneDeep'
import {
asyncVessel
} from '@/utils/tool'
export const injectMark = 'MANAGE_TABLE'
/**
*
* @param { Function } update 表格数据请求接口
* @param { Object } initQuery 搜素条初始参数
* @param { Object } options 设置项
*/
export default function tableHook( update, initQuery={}, options={}){
// 默认配置
const defOptions = {
pageSize: 10,
totalCount: 0,
currentPage: 1,
tableList: [],
}
const state = reactive(Object.assign({}, defOptions, options))
// 表格对象,用于获取对象上的方法
const tableEle = ref(null)
// 设置搜索条参数
const setQuery = (initQuery) => reactive({
pageSize: computed(() => state.pageSize),
pageNo: computed(() => state.currentPage),
...cloneDeep(initQuery),
})
// 重置搜索条参数
let query = ref(setQuery(initQuery))
// 向外开放查询参数
watch(() => query.value, () => state.localCopyQuery&&state.localCopyQuery(query.value))
// 搜索条重置
const resetQuery = () => query.value = setQuery(initQuery)
// 请求表格数据
async function onSearch(params=query.value){
const [ res, err ] = await asyncVessel(update(params))
if(err){
console.error('TABLE_ERROR: ', err)
return
}
const { result, totalCount } = res
state.tableList = result
state.totalCount = totalCount
}
// 分页选择
const onCurrentChange = num => {
state.currentPage = num
onSearch()
}
// 重置表格数据
const restTable = () => {
resetQuery()
onCurrentChange(1)
}
// 初始请求
restTable()
return {
query,
tableEle,
restTable,
resetQuery,
onSearch,
onSearchNoQuery: () => onSearch(),
onCurrentChange,
...toRefs(state)
}
}
<template>
<div style="margin-bottom: 40px">
<el-card shadow="hover" body-style="padding: 0">
<DefTableTopbar @search='onSearchHandler' @reset='onResetHandler' />
<div style="padding: 20px; padding-bottom: 2px">
<Form :itemsConf='searchBarConf' :model='query' />
</div>
</el-card>
</div>
</template>
<script>
import DefTableTopbar from './searchbar-btns'
import Form from '../form-container/index.vue'
import { toRefs, inject } from '@vue/composition-api'
import { injectMark } from './table-hook'
export default {
components: {
DefTableTopbar,
Form
},
props: {
searchBarConf:{
default(){return {}}
},
},
setup(){
const allState = inject(injectMark)
const onSearchHandler = () => {
allState.currentPage = 1
allState.onSearch()
}
const onResetHandler = () =>{
allState.restTable()
}
return {
onSearchHandler,
onResetHandler,
...toRefs(allState)
}
}
}
</script>
<template>
<div style='margin-top: 20px'>
<el-card bodyStyle="padding: 10px 20px" shadow='hover'>
<Pagination
@current-change='onCurrentChange'
:total='totalCount'
:pageSize='pageSize'
:currentPage='currentPage' >
</Pagination>
</el-card>
</div>
</template>
<script>
import { toRefs, inject } from '@vue/composition-api'
import { injectMark } from './table-hook'
const Pagination = ctx => {
const _defaultConf = {
['layout']: ['total', 'prev', 'pager', 'next', 'jumper'].join(','),
['current-page']: '',
['page-sizes']: [10],
['page-size']: 10,
['total']: 0,
['currentPage']: 1,
}
if(ctx.props){
ctx.props = Object.assign({}, _defaultConf, ctx.props)
}
return (
<el-pagination style={{padding:0, marginTop:0}} { ...ctx } on={ ctx.listeners } ></el-pagination>
)
}
export default {
components: {
Pagination
},
setup(){
const allState = inject(injectMark)
return toRefs(allState)
}
}
</script>
import CadTopBar from '@/components/card-top-bar'
import { inject } from '@vue/composition-api'
import { injectMark } from './table-hook'
const Table = {
props:{
tableConf:{
default(){return {}}
},
},
setup(props){
const allState = inject(injectMark)
return {
tableList: allState.tableList
}
},
render(){
const { tableList, tableConf } = this
// 表格列
const tableColumns = tableConf.columns.map((item, index) =>{
// child 插槽
if(item.child){
const Cmp = item.child
const scopedSlots = {
default: slotprops => [
<Cmp slotprops={slotprops} on={ item.on } attrs={ item } ></Cmp>
]
}
return <el-table-column key={index} props={item} scopedSlots={scopedSlots} ></el-table-column>
}
// slot 插槽
if(item.slot){
const Cmp = this.$scopedSlots[ typeof item.slot === 'string' ? item.slot : item.prop]
if(!Cmp) return
const scopedSlots ={
default: slotprops => [
Cmp(slotprops),
]
}
return <el-table-column key={index} props={item} scopedSlots={scopedSlots} ></el-table-column>
}
// 默认column
return <el-table-column key={index} props={item} ></el-table-column>
})
// topbar 插槽
let Topbar = this.$slots['table-top-bar']
return (
<el-card body-style='padding: 0' shadow='hover' >
<CadTopBar title='数据列表'>
{ Topbar }
</CadTopBar>
<el-table ref='tableEle' data={ tableList } listeners={ tableConf.on } attrs={ tableConf.props } >
{ tableColumns }
</el-table>
</el-card>
)
}
}
export default Table